1 Introduction

Bulk RNA sequencing data on 24 pre-treatment breast cancer tumours performed by Wu et al. [1] was downloaded from GEO with accession GSE176078, and associated publication.

geo_id <- "GSE176078"

This dataset was sequenced using Illumina NextSeq 500 (Homo sapiens), submitted on Apr 15 2014.

Breast cancers are clinically stratified based on:

  • expression of the estrogen receptor (ER),
  • expression of the progesterone receptor (PR), and
  • overexpression of HER2 (or amplification of HER2 gene ERBB2)

This results in the following three clinical subtypes within this dataset:

  • Luminal ie. ER+; (ER+, PR+/-)
  • HER2+; (HER2+, ER+/-, PR+/-)
  • Triple Negative ie. TNBC; (ER-, PR-, HER2-)

Breast cancers are also stratified on bulk transcriptomic profiling via PAM50 gene signatures [2] describing five molecular subtypes: Luminal A, Luminal B, HER2-enriched, Basal-like, and Normal-like.

The ~70-80% concordance between clinical and molecular subtypes motivated this study to improve functional understanding of breast cancer in a broader and more coherent sense.

For this study, the clinical subtype conditions classified are as follows:

  • HER2+ ; (HER2+, ER-, PR+/-)
  • HER2+/ER+ ; (HER2+, ER+, PR+/-)
  • ER+ ; (HER2-, ER+, PR+/-)
  • TNBC ; (HER2-, ER-, PR-)

The distribution of clinical subtypes across the 24 samples is shown in table 1.

Table 1: Clinical breast cancer subtype splits in our dataset
Count Percent
HER2+ 2 8.33
HER2+/ER+ 2 8.33
TNBC 8 33.33
ER+ 12 50.00
Total 24 100.00

This leads to 16.6666667% of samples containing HER2 expression, and 41.6666667% of samples containing ER expression, with the overlaps of these representing 8.3333333% of all samples; 50% of those with HER2, 14.2857143% of those with ER.

The raw counts were cleaned, mapped to HUGO Gene Nomenclature Committee (HGNC) Symbols, and normalized to produce final counts which will be used for the duration of this report.

Of the original 58387 genes, we were able to map and produce 28712 unversioned, unique genes, of which filtering outliers (keeping genes present in a minimum of 12 samples) resulted in 14800 genes remaining. This results in the following plots.

The density plot shows the distribution of the cleaned, filtered, and normalized counts per million across all samples (varying colours). It displays a smooth curve as the result of our pre-processing.


Figure 1: Density of minimum 12 samples filtered and normalized CPM counts for 24 samples across four clinical subtypes of breast cancer tissue
Figure 1: Density of minimum 12 samples filtered and normalized CPM counts for 24 samples across four clinical subtypes of breast cancer tissue


Dispersion was calculated using edgeR to describe deviation of variance from the mean. The Biological Coefficient of Variation (BCV) is dispersion-squared, and represents the mean-variance relationship among genes.

Figure 2: Biological Coefficient of Variation (Dispersion squared) for 24 samples across four clinical subtypes of breast cancer tissue gene-wise
Figure 2: Biological Coefficient of Variation (Dispersion squared) for 24 samples across four clinical subtypes of breast cancer tissue gene-wise


The normalized counts initialized above are formatted as shown by the subsection displayed in table 2.

Table 2: Format of Normalized counts dataset as described above
CID3586 CID3921 CID3941 CID3948 CID3963
WASH7P 17.5790 1.0450 14.7274 0.0000 28.5314
CICP27 1.9276 3.6553 2.2895 0.0000 2.1353
MTND2P28 175.8840 174.5844 168.6025 354.9525 450.4684
MTATP6P1 413.8903 589.8450 462.3509 1053.1526 404.6456
FAM87B 2.6751 1.9207 2.7736 1.5650 2.4742
LINC01128 26.6312 35.3648 17.6844 20.9555 21.8894

2 Differential Gene Expression

Given our normalized expression dataset contains only grouped classification via clinical subtypes, these are the obvious choice for factors. But, due to the nature of these classifiers, the names themselves represent binary pairing of HER2 and ER expression and absence (in a clinical setting). This provides some flexibility for analyzing differential expression since we really have two protein expressions, with their binary pairing as the clinical subtype classification.

The Multi-Dimensional Scaling (MDS) plot was produced using limma on the normalized data, and it shows the distance between samples factored by the four distinct clinical subtypes.

In the given MDS plot, notice that blue and red are opposites (+/- and -/+), purple is the intermediary between blue and red (+/+), whereas green represents TNBC: double negative (-/-). Although progesterone is a marker for breast cancer, its expression is not quantifiably present within the dataset, and so is not included. However, TNBC implies PR is not overly expressed as well.

In terms of these colours in relation to each other, you can see some clustering appearing, although nothing is confidently distinct.

2.1 Calculate p-values for each gene.

I redefine the model to include the clinical subtypes of breast cancer as factors, both as four separate classifiers, and the binary pairing of over/under expression of HER2 and ER.

# aggregate model design
model_design <- model.matrix(~ types_df$subtype)

# split model design (binary pairs)
splt_model_design <- model.matrix(~ types_df$her2 + types_df$er)

Given both design choices, I used edgeR’s Quasi likelihood model to create quasi-likelihood fits.

# normalized counts grouped by clinical subtype
d <- DGEList(counts=norm_matrix, 
             group=types_df$subtype)

# estimate dispersion on subtype model design
d_ <- estimateDisp(d, model_design)
qlfit <- glmQLFit(d_, model_design)

# in parallel, estimate dispersion on binary pairing model design
d_splt <- estimateDisp(d, splt_model_design)
qlfit_splt <- glmQLFit(d_splt, splt_model_design)

Now, we can use glmQLFTest to calculate the differential expression according to this model.

# fit subtype model design
qlf.subtypes <- glmQLFTest(qlfit)
# fit split model design
qlf.her2p <- glmQLFTest(qlfit_splt, 
                        coef='types_df$erTRUE')
qlf.erp <- glmQLFTest(qlfit_splt, 
                      coef='types_df$her2TRUE')

At this point, we analyze the calculated p-values and aggregate our top hits for each model.

# top tags for aggregate model design
top_hits <- topTags(qlf.subtypes, 
                    sort.by = "PValue",
                    n = nrow(normalized_counts))

# tog tags for split model design
top_her2p <- topTags(qlf.her2p,
                     sort.by = "PValue",
                     n = nrow(normalized_counts))
top_erp <- topTags(qlf.erp,
                   sort.by = "PValue",
                   n = nrow(normalized_counts))

2.1.1 How many genes were significantly differentially expressed?

For our three model designs (one aggregate, and two binary splits), the following number of genes were significantly differentially expressed before correction.

Table 3: Number of P-Values that are significantly differentially expressed for the three different model designs
Significantly Differentially Expressed Genes
Aggregate across subtypes 1462
HER2 expression 1240
ER expression 779

2.1.2 What thresholds did you use and why?

A threshold of 0.05 for p-values is very standard. It implies that statistically we will only achieve this outcome 5% of the time assuming the null hypothesis is true (our null hypothesis being that there is no differential expression between the clinical subtypes in these genes).

If I continued this analysis and found that I had a lot of genes remaining, I could lower the threshold, but 0.05 is a solid starting point with that in mind.

2.2 Multiple hypothesis testing

edgeR’s analysis provides a FDR value, which implies Benjamini-Hochberg, however I wanted to independently verify.

corrected_top_hits <- p.adjust(top_hits$table$PValue, 
                               method = "BH", 
                               n = nrow(normalized_counts))
length(which(corrected_top_hits < 0.05))
[1] 3

So, using this correction method, only 3 genes pass correction for significant differential expression.

2.2.1 Which method did you use? and why?

As described, the False Discovery Rates provided by our analysis match my independent understanding of the Benjamini-Hochberg method.

This method is very applicable to our use-case since it is less stringent than Bonferroni when it comes to having a large number of hypotheses. It is best practice to use Benjamini-Hochberg first to see which of your genes pass correction, and if you need a more stringent corrective method, you can consider using Bonferroni. However, Bonferroni is said to be more useful when you are testing a smaller number of hypotheses which is generally not the case for RNA sequencing data.

2.2.2 How many genes passed correction?

For our two model designs, the following number of genes passed correction for each classifier.

Table 4: Number of P-Values that are significantly differentially expressed for the three different model designs
Significantly Differentially Expressed Genes Significantly Differentially Expressed Genes after correction
Aggregate across subtypes 1462 3
HER2 expression 1240 0
ER expression 779 11

There is clearly a large reduction in number of genes significantly differentially expressed.

For the aggregate model of clinical subtypes, only 3 genes passed correction for false discovery. No genes passed correction for HER2 expression association, whereas 11 genes passed correction for ER expression association.

The genes and their associated values are shown in the tables below.

2.3 Amount of differentially expressed genes

2.3.1 MA Plot

An MA Plot demonstrates the log-fold change in contrast to the log-concentration for our counts. I use edgeR’s MA plot functionality for both model designs.

edgeR::maPlot(logAbundance=top_hits$table$logCPM, 
              logFC=top_hits$table$logFC,
              de.tags=which(top_hits$table$FDR < 0.05),
              lowess=TRUE,
              xlab="log(counts per million)",
              ylab="log(fold-change)",
              main="Figure 4: MA Plot of significantly differentially 
              expressed genes after correction across 
              clinical subtypes, aggregate design")
legend("topright", title="Significance",
       legend=c("not significant", 
                "significant after correction"), 
       col=c("black", "red"), pch=1, cex=0.8)

edgeR::maPlot(logAbundance=top_erp$table$logCPM, 
              logFC=top_erp$table$logFC,
              de.tags=which(top_erp$table$FDR < 0.05),
              lowess=TRUE,
              xlab="log(counts per million)",
              ylab="log(fold-change)",
              main="Figure 5: MA Plot of significantly differentially 
              expressed genes after correction 
              associated with ER expression")
legend("topright", title="Significance",
       legend=c("not significant", 
                "significant after correction"), 
       col=c("black", "red"), pch=1, cex=0.8)

2.3.2 Volcano Plot

The volcano plot provides another visual for the spread of our differentially expressed genes and their significance, both before and after correction.

The green points are those with significant p-values before correction, with the red points being significant genes after correction.

plot(top_hits$table$logFC, -10*log10(top_hits$table$PValue),
     main="Figure 6: Volcano Plot of significantly differentially 
     expressed genes after correction 
     across clinical subtypes, aggregate design",
     xlab="log(fold change)",
     ylab="-10^log(p-value)")
# highlight differentially expressed genes
points(top_hits$table$logFC[which(top_hits$table$PValue < 0.05)],
       -10*log10(top_hits$table$PValue)[which(top_hits$table$PValue < 0.05)],
       col="green")
points(top_hits$table$logFC[which(top_hits$table$FDR < 0.05)],
       -10*log10(top_hits$table$PValue)[which(top_hits$table$FDR < 0.05)],
       col="red")
legend("topleft", title="Significance",
       legend=c("not significant", 
                "significant before correction", 
                "significant after correction"), 
       col=c("black", "green", "red"), pch=1, cex=0.8)

plot(top_erp$table$logFC, -10*log10(top_erp$table$PValue),
     main="Figure 7: Volcano Plot of significantly differentially 
     expressed genes after correction 
     associated with ER expression",
     xlab="log(fold change)",
     ylab="-10^log(p-value)")
# highlight differentially expressed genes
points(top_erp$table$logFC[which(top_erp$table$PValue < 0.05)],
       -10*log10(top_erp$table$PValue)[which(top_erp$table$PValue < 0.05)],
       col="green")
points(top_erp$table$logFC[which(top_erp$table$FDR < 0.05)],
       -10*log10(top_erp$table$PValue)[which(top_erp$table$FDR < 0.05)],
       col="red")
legend("topleft", title="Significance",
       legend=c("not significant", 
                "significant before correction", 
                "significant after correction"), 
       col=c("black", "green", "red"), pch=1, cex=0.8)

This volcano plot of differentially expressed genes with regards to ER- and ER+ is very interesting given its strong skew towards up-regulation.

plot(top_her2p$table$logFC, -10*log10(top_her2p$table$PValue),
     main="Figure 8: Volcano Plot of significantly differentially 
     expressed genes after correction 
     associated with HER2 expression",
     xlab="log(fold change)",
     ylab="-10^log(p-value)")
# highlight differentially expressed genes
points(top_her2p$table$logFC[which(top_her2p$table$PValue < 0.05)],
       -10*log10(top_her2p$table$PValue)[which(top_her2p$table$PValue < 0.05)],
       col="green")
points(top_her2p$table$logFC[which(top_her2p$table$FDR < 0.05)],
       -10*log10(top_her2p$table$PValue)[which(top_her2p$table$FDR < 0.05)],
       col="red")
legend("topleft", title="Significance",
       legend=c("not significant", 
                "significant before correction", 
                "significant after correction"), 
       col=c("black", "green", "red"), pch=1, cex=0.8)

Both the aggregate model design, and the HER2 design are fairly evenly distributed around 0.

2.4 Visualizing top hits

2.4.1 Heatmap

Aggregating our top hits across clinical subtypes into a heatmap, we can see the expression visually as shown, along with a heatmap annotation corresponding to each binary pairing represented by the subtype classifier.

tops <- rownames(qlf.subtypes$table)[
  qlf.subtypes$table$PValue < 0.05
]
top_hits_matrix = t(scale(
  t(norm_matrix[which(rownames(norm_matrix) %in% tops),])
))

# colours
if (min(top_hits_matrix) == 0) {
  heatmap_col = colorRamp2(c(0, max(top_hits_matrix)),
                           c("white", "red"))
} else {
  heatmap_col = colorRamp2(c(min(top_hits_matrix), 0, max(top_hits_matrix)),
                           c("blue", "white", "red"))
}

# annotations
her2_col <- c("lightgreen", "red")
names(her2_col) <- c('TRUE', 'FALSE')
er_col <- c("darkgreen", "pink")
names(er_col) <- c('TRUE', 'FALSE')

types_df$her2 <- factor(types_df$her2, levels = c('TRUE','FALSE'))
types_df$er <- factor(types_df$er, levels = c('TRUE','FALSE'))

heatmap_annotation <- ComplexHeatmap::HeatmapAnnotation(
  df = data.frame(her2 = types_df$her2,
                  er = types_df$er),
  col = list(her2 = her2_col, er = er_col),
  show_legend=TRUE
)

heatmap <- ComplexHeatmap::Heatmap(as.matrix(top_hits_matrix),
                                   cluster_rows=TRUE,
                                   cluster_columns=TRUE,
                                   show_row_dend=TRUE, 
                                   show_column_dend=TRUE,
                                   col=heatmap_col, 
                                   show_column_names=FALSE,
                                   show_row_names=FALSE, 
                                   show_heatmap_legend=TRUE,
                                   name="colour scale",
                                   top_annotation=heatmap_annotation,
                                   column_title="Figure 9: Heatmap of top hits across 
                                   clinical subtypes, aggregate design")

Specifically for ER overexpression or lack thereof, I added an additional heatmap.

tops_er <- rownames(qlf.erp$table)[
  qlf.erp$table$PValue < 0.05
]
tops_er_matrix = t(scale(
  t(norm_matrix[which(rownames(norm_matrix) %in% tops_er),])
))

# colours
if (min(tops_er_matrix) == 0) {
  heatmap_col = colorRamp2(c(0, max(tops_er_matrix)),
                           c("white", "red"))
} else {
  heatmap_col = colorRamp2(c(min(tops_er_matrix), 0, max(tops_er_matrix)),
                           c("blue", "white", "red"))
}

heatmap_er <- ComplexHeatmap::Heatmap(as.matrix(tops_er_matrix),
                                      cluster_rows=TRUE,
                                      cluster_columns=TRUE,
                                      show_row_dend=TRUE, 
                                      show_column_dend=TRUE,
                                      col=heatmap_col, 
                                      show_column_names=FALSE,
                                      show_row_names=FALSE, 
                                      show_heatmap_legend=TRUE,
                                      name="colour scale",
                                      top_annotation=heatmap_annotation,
                                      column_title="Figure 10: Heatmap of top hits 
                                      associated with ER overexpression")

2.4.2 Do conditions cluster together? Explain.

In figure 9, there is very visibly a cluster demonstrated between heat intensity and ER overexpression or lack thereof with the genes primarily in the top half being generally highly expressed in lack of ER, and lowly expressed in overexpression of ER. Similarly, the lower half of genes primarily follow the opposite trend; lower expression on ER- and higher expression on ER+.

In figure 10, it is more difficult to see the cluster patterns. Sample 1 has very intense RNA expressions in the top half of genes, but its matching HER2+/ER- subtype lacks this at all. This implies the association goes in a broader scale than lack of ER for these genes. Despite 11 genes being associated with overexpression of ER, it does not appear to show a visible cluster on the heatmap like the aggregate design in figure 9 does pretty well.

3 Thresholded Over-Representation Analysis

With our significantly up-regulated, and down-regulated gene-sets, we will run a thresholded gene-set enrichment analysis.

We have 807 up-regulated genes, and 655 down-regulated genes for our aggregate model design across all clinical subtypes.

# create non-thresholded gene sets
nt_geneset <- qlf.subtypes$table
nt_geneset[,"rank"] <- -log10(nt_geneset$PValue) * sign(nt_geneset$logFC)
nt_geneset <- nt_geneset[order(nt_geneset$rank),]
# create thresholded up and down gene sets
upreg <- rownames(nt_geneset)[which(nt_geneset$PValue < 0.05
                                    & nt_geneset$logFC > 0)]
downreg <- rownames(nt_geneset)[which(nt_geneset$PValue < 0.05
                                      & nt_geneset$logFC < 0)]
# function for retrieving g:GOSt from g:Profiler
gost_res <- function(query) {
  res <- gost(query = query,
                      significant=FALSE, # set our own threshold
                      ordered_query = TRUE, # ordered by rank
                      exclude_iea=TRUE, # exclude electronic GO annotations
                      correction_method = "fdr", # BH
                      organism = "hsapiens",
                      source = c("REAC","WP","GO:BP", 
                                 "GO:CC", "GO:MF", "KEGG"))
  return(res)
}

I query our genesets using g:Profiler’s g:GOSt.

# up and down regulated thresholded genes
all <- gost_res(unique(c(upreg, downreg)))
# only up regulated thresholded genes
up <- gost_res(upreg)
# only down regulated thresholded genes
down <- gost_res(downreg)
Table 7: Head of thresholded up and down regulated genes from g:GOSt
p_value term_id term_name
0.018483 GO:0046032 ADP catabolic process
0.018483 GO:0046031 ADP metabolic process
0.018483 GO:0006096 glycolytic process
0.018483 GO:0009057 macromolecule catabolic process
0.018483 GO:0009137 purine nucleoside diphosphate catabolic process
Table 8: Head of thresholded up-regulated genes from g:GOSt
p_value term_id term_name
0.0151737 GO:0022613 ribonucleoprotein complex biogenesis
0.0151737 GO:0009179 purine ribonucleoside diphosphate metabolic process
0.0151737 GO:0009181 purine ribonucleoside diphosphate catabolic process
0.0151737 GO:0009056 catabolic process
0.0151737 GO:0046032 ADP catabolic process
Table 9: Head of thresholded down-regulated genes from g:GOSt
p_value term_id term_name
0.0666454 GO:0031000 response to caffeine
0.0666454 GO:0071871 response to epinephrine
0.0666454 GO:0071872 cellular response to epinephrine stimulus
0.0666454 GO:0032989 cellular anatomical entity morphogenesis
0.0666454 GO:0055006 cardiac cell development

3.1 Which method did you choose and why?

I chose to use g:Profiler with R since it was well documented by Ruth Isserlin [3] and I had familiarity with it through my journal entry.

g:Profiler provides an ORA (over-representation analysis) method, and this is exactly the method I want to perform on my thresholded data.

3.2 Which annotation data did you use and why?

I chose the following annotation sources to get the most comprehensive results for our functional enrichment analysis relative to biological processes and gene ontology:

  • GO:BP : Gene Ontology: Biological Processes
  • REAC : Reactome
  • WP : WikiPathways
  • GO:CC : Gene Ontology: Cellular Components
  • GO:MF : Gene Ontology: Molecular Function
  • KEGG : Kyoto Encyclopedia of Genes and Genomes

GO:BP, REAC, and WP were recommended by Professor Isserlin, however I ran the ORA using these and found nothing jumped out from the resulting plots. As such, I revisited to expand the scope of annotation sources in hopes for a more informative result.

3.2.1 What version of the annotation are you using?

For g:Profiler version information, I used:

  • g:Profiler version: e112_eg59_p19_25aa4782
  • biomaRt version: 112

For the annotation sources selected in my query, I used:

  • GO:BP version annotations: BioMart classes: releases/2024-10-27
  • REAC version annotations: BioMart classes: 2025-2-3
  • WP version 20250110
  • GO:CC version annotations: BioMart classes: releases/2024-10-27
  • GO:MF version annotations: BioMart classes: releases/2024-10-27
  • KEGG version KEGG FTP Release 2024-01-22

3.3 How many gene-sets were returned with what thresholds?

Table 10: Gene-set sizes for different maximum thresholds with minimum intersection of 5
Max 100 Max 250 Max 1000 Max 100000
Up & Down 991 1646 2160 2380
Up 558 1123 1610 1829
Down 126 324 570 643
Table 11: Gene-set sizes for different maximum thresholds with minimum intersection of 10
Max 100 Max 250 Max 1000 Max 100000
Up & Down 119 514 942 1132
Up 49 314 698 886
Down 6 49 152 193

After thresholding with maximum value of 100 and minimum intersection of 10, we can see the terms remain similar.

Table 12: Head of thresholded [3, 100] up and down-regulated genes from ORA with intersection 10
term_id term_name p_value significant
1 GO:0046032 ADP catabolic process 0.018483 TRUE
2 GO:0046031 ADP metabolic process 0.018483 TRUE
3 GO:0006096 glycolytic process 0.018483 TRUE
5 GO:0009137 purine nucleoside diphosphate catabolic process 0.018483 TRUE
6 GO:0019364 pyridine nucleotide catabolic process 0.018483 TRUE
Table 13: Head of thresholded [3, 100] up-regulated genes from ORA with intersection 10
term_id term_name p_value significant
2 GO:0009179 purine ribonucleoside diphosphate metabolic process 0.0151737 TRUE
3 GO:0009181 purine ribonucleoside diphosphate catabolic process 0.0151737 TRUE
5 GO:0046032 ADP catabolic process 0.0151737 TRUE
7 GO:0046031 ADP metabolic process 0.0151737 TRUE
8 GO:0006096 glycolytic process 0.0151737 TRUE
Table 14: Head of thresholded [3, 100] down-regulated genes from ORA with intersection 10
term_id term_name p_value significant
4 GO:0032989 cellular anatomical entity morphogenesis 0.0666454 FALSE
7 GO:0010927 cellular component assembly involved in morphogenesis 0.0666454 FALSE
48 GO:0035051 cardiocyte differentiation 0.0676004 FALSE
135 GO:0010469 regulation of signaling receptor activity 0.0937527 FALSE
4333 GO:0005796 Golgi lumen 0.0532868 FALSE

As such, we find that up-regulated genes have some significant gene-sets after thresholding, whereas our down-regulated genes fail to maintain significance.

Our combination table shows us strong overlap with the up-regulated genes, further supporting the significance of our up-regulation skewed results.

3.4 Comparing up-regulated and down-regulated separate vs. together

The following figures demonstrate the over-representation analysis plots for both up & down regulated, up-regulated, and down-regulated genes respectively with only a couple of points manually highlighted.

Figure 11: Over-representation analysis of Up and Down regulated significantly differentially expressed genes
Figure 11: Over-representation analysis of Up and Down regulated significantly differentially expressed genes


Figure 12: Over-representation analysis of Up-regulated significantly differentially expressed genes
Figure 12: Over-representation analysis of Up-regulated significantly differentially expressed genes


Figure 13: Over-representation analysis of Down-regulated significantly differentially expressed genes
Figure 13: Over-representation analysis of Down-regulated significantly differentially expressed genes

3.4.1 How do these results compare?

Since the up-regulated gene results tend to exceed the down-regulated gene results in terms of term significance, the combined plot appears to more closely resemble the up-regulated plot.

In our case, ORA of up and down-regulated genes in combination did not have a large effect on the results, but this is because the up-regulated genes overshadow the down-regulated. If this were a different case, we could see the difference between the up- and down-regulated plots overshadowed and melted by the combination plot. As such, it is important to look at both up- and down-regulated separately.

Although, in terms of our results of this analysis, although some terms are significant according to our arbitrary threshold, none of them are strikingly so with maximum -log(adjusted p-values) only reaching up to about 3 maximum, whereas plots seen with stronger functional enrichment presence reach up much higher towards 10-16+.

4 Interpretation

4.1 Do the over-representation results support conclusions or mechanisms discussed in the original paper?

The original paper includes substantially more processing of this data in addition to the single-cell RNA sequencing data they acquired in tandem, so it is difficult to say whether this supports those results. None of my significant differentially expressed genes appear throughout the report whatsoever. The discussion and results section for the bulk RNA-sequencing is very lackluster compared to the rest of the analysis and results found by spatial resolution of single-cell RNA sequencing. The RNA sequencing heatmap appears similar to mine, although they used scaled mean interaction score and subtyped only for ER and TNBC as opposed to the four available clinical subtypes. I can understand this approach since the HER2 subtype presence was relatively small compared to the rest of the samples.

There is not much functional enrichment apparently distinguishing the classified clinical subtypes of breast cancer in this dataset; although if we had to look at the most significant term(s), our analysis would draw our attention to cadherin binding, ie. GO:0045296, of which is not present in the paper’s conclusions. As such, my findings do not support the mechanisms or conclusions discussed in the original paper, although that does not deny my findings.

4.2 Can you find evidence, ie. publications, to support some of the results that you see? How does this evidence support your results?

Continuing with the most significant GO term from our analysis–cadherin binding–there is substantial evidence that cadherins are integral to mammary gland function, and misexpression of such leads to increased motility and consequently greater likelihood of metastases formation [4]. E-cadherin is one of the most widely expressed tumour suppressors in breast cancer, however cadherin-binding on its own is rather vague and difficult to draw conclusions from. We can conclude, however, that cadherins are associated with breast cancer in multiple ways, and so cadherin-binding may be a distinguishable functional enrichment between clinical subtypes–but this claim is too general to confidently back.

Interestingly, one of our three significantly differentially expressed genes after correction across clinical subtypes of breast cancer is ANXA8 which is associated with breast cancer [5]. Rosetti et al. suggested ANXA8 is significantly higher in ER- subtypes as opposed to ER+ subtypes [6] but instead of finding that in our results, we noticed ANXA8 was significantly differentially expressed across all clinical subtypes classified in our study and not specifically ER overexpression or lack thereof. This warrants investigation into why ANXA8 is expressed differentially in ER subtypes according to research, yet selectively expressed differentially across all four of our classified clinical subtypes of breast cancer, and not specifically for ER in-silico.

In terms of significantly differentially expressed genes in regards to ER- and ER+ specifically, the most significant gene is EPHA3 which has been shown to be extensively more up-regulated in ER+ breast cancers [7], which directly supports my findings. Although my findings were not reflective of the mechanisms and direction of the paper I retrieved the data from, they are supported by other evidence in certain ways.

In conclusion, there is some associated evidence that suggests my results have a foundation in functional biology, however nothing has a significance that would give me confidence to back my claim. For this, I would want a p-value smaller than 10e-3.

5 Acknowledgments

This paper makes use of packages knitr [8], BiocManager [9], GEOquery [10], kableExtra [11], edgeR [12], limma [13], ComplexHeatmap [14], circlize [15], gprofiler2 [16], GSA [17], & ggplot2 [18].

6 Bibliography

1. Wu SZ, Al-Eryani G, Roden DL, Junankar S, Harvey K, Andersson A, et al. A single-cell and spatially resolved atlas of human breast cancers. Nature genetics. 2021;53:1334–47.
2. Parker JS, Mullins M, Cheang MC, Leung S, Voduc D, Vickery T, et al. Supervised risk predictor of breast cancer based on intrinsic subtypes. Journal of clinical oncology. 2009;27:1160–7.
3. Isserlin R. Run g:profiler from r.
4. Derycke LD, Bracke ME. N-cadherin in the spotlight of cell-cell adhesion, differentiation, embryogenesis, invasion and signalling. International Journal of Developmental Biology. 2004;48:463–76.
5. LifeMap Sciences Inc. MalaCards human disease database.
6. Rossetti S, Bshara W, Reiners JA, Corlazzoli F, Miller A, Sacchi N. Harnessing 3D models of mammary epithelial morphogenesis: An off the beaten path approach to identify candidate biomarkers of early stage breast cancer. Cancer letters. 2016;380:375–83.
7. Liang Z, Wang X, Dong K, Li X, Qin C, Zhou H. Expression pattern and prognostic value of EPHA/EFNA in breast cancer by bioinformatics analysis: Revealing its importance in chemotherapy. BioMed Research International. 2021;2021:5575704.
8. Xie Y. Dynamic documents with R and knitr. 2nd edition. Boca Raton, Florida: Chapman; Hall/CRC; 2015.
9. Morgan M, Ramos M. BiocManager: Access the bioconductor project package repository. 2024.
10. Davis S. GEOquery: Get data from NCBI gene expression omnibus (GEO). 2024.
11. Zhu H. kableExtra: Construct complex table with ’kable’ and pipe syntax. 2024.
12. Chen Y, Lun AT, McCarthy DJ, Chen L, Baldoni P, Ritchie ME, et al. edgeR: Empirical analysis of digital gene expression data in r. 2025.
13. Ritchie ME, Phipson B, Wu D, Hu Y, Law CW, Shi W, et al. limma powers differential expression analyses for RNA-sequencing and microarray studies. Nucleic Acids Research. 2015;43:e47.
14. Gu Z. Complex heatmap visualization. iMeta. 2022. https://doi.org/10.1002/imt2.43.
15. Gu Z, Gu L, Eils R, Schlesner M, Brors B. Circlize implements and enhances circular visualization in r. Bioinformatics. 2014;30:2811–2.
16. Kolberg L, Raudvere U, Kuzmin I, Vilo J, Peterson H. gprofiler2– an r package for gene list functional enrichment analysis and namespace conversion toolset g:profiler. F1000Research. 2020;9 (ELIXIR).
17. Efron B, Tibshirani R. GSA: Gene set analysis. 2024.
18. Wickham H, Chang W, Henry L, Pedersen TL, Takahashi K, Wilke C, et al. ggplot2: Create elegant data visualisations using the grammar of graphics. 2024.
LS0tCnRpdGxlOiAiQXNzaWdubWVudCAyIgpzdWJ0aXRsZTogIkRpZmZlcmVudGlhbCBHZW5lIEV4cHJlc3Npb24gYW5kIFByZWxpbWluYXJ5IE9SQSIKYXV0aG9yOiAiQW5uYWJlbGxhIEJyZWdhenppIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKYmlibGlvZ3JhcGh5OiBhMl9yZWZlcmVuY2VzLmJpYgpjc2w6IGJpb21lZC1jZW50cmFsLmNzbApsaW5rLWNpdGF0aW9uczogdHJ1ZQotLS0KCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CmxpYnJhcnkoa25pdHIpCmlmICghcmVxdWlyZSgiQmlvY01hbmFnZXIiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJCaW9jTWFuYWdlciIpCgp0cnlDYXRjaChleHByID0geyBsaWJyYXJ5KCJHRU9xdWVyeSIpfSwgCiAgICAgICAgIGVycm9yID0gZnVuY3Rpb24oZSkgeyAKICAgICAgICAgICBpbnN0YWxsLnBhY2thZ2VzKCJHRU9xdWVyeSIpfSwgCiAgICAgICAgIGZpbmFsbHkgPSBsaWJyYXJ5KCJHRU9xdWVyeSIpKQp0cnlDYXRjaChleHByID0geyBsaWJyYXJ5KCJrYWJsZUV4dHJhIil9LCAKICAgICAgICAgZXJyb3IgPSBmdW5jdGlvbihlKSB7IAogICAgICAgICAgIGluc3RhbGwucGFja2FnZXMoImthYmxlRXh0cmEiKX0sIAogICAgICAgICBmaW5hbGx5ID0gbGlicmFyeSgia2FibGVFeHRyYSIpKQp0cnlDYXRjaChleHByID0geyBsaWJyYXJ5KCJlZGdlUiIpfSwgCiAgICAgICAgIGVycm9yID0gZnVuY3Rpb24oZSkgeyAKICAgICAgICAgICBpbnN0YWxsLnBhY2thZ2VzKCJlZGdlUiIpfSwgCiAgICAgICAgIGZpbmFsbHkgPSBsaWJyYXJ5KCJlZGdlUiIpKQp0cnlDYXRjaChleHByID0geyBsaWJyYXJ5KCJsaW1tYSIpfSwgCiAgICAgICAgIGVycm9yID0gZnVuY3Rpb24oZSkgeyAKICAgICAgICAgICBpbnN0YWxsLnBhY2thZ2VzKCJsaW1tYSIpfSwgCiAgICAgICAgIGZpbmFsbHkgPSBsaWJyYXJ5KCJsaW1tYSIpKQppZiAoIXJlcXVpcmUoIkNvbXBsZXhIZWF0bWFwIiwgcXVpZXRseSA9IFRSVUUpKQogICAgQmlvY01hbmFnZXI6Omluc3RhbGwoIkNvbXBsZXhIZWF0bWFwIikKaWYgKCFyZXF1aXJlKCJjaXJjbGl6ZSIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJjaXJjbGl6ZSIpCnRyeUNhdGNoKGV4cHIgPSB7IGxpYnJhcnkoImdwcm9maWxlcjIiKX0sIAogICAgICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIHsgCiAgICAgICAgICAgaW5zdGFsbC5wYWNrYWdlcygiZ3Byb2ZpbGVyMiIpfSwgCiAgICAgICAgIGZpbmFsbHkgPSBsaWJyYXJ5KCJncHJvZmlsZXIyIikpCnRyeUNhdGNoKGV4cHIgPSB7IGxpYnJhcnkoIkdTQSIpfSwgCiAgICAgICAgIGVycm9yID0gZnVuY3Rpb24oZSkgeyAKICAgICAgICAgICBpbnN0YWxsLnBhY2thZ2VzKCJHU0EiKX0sIAogICAgICAgICBmaW5hbGx5ID0gbGlicmFyeSgiR1NBIikpCnRyeUNhdGNoKGV4cHIgPSB7IGxpYnJhcnkoImdncGxvdDIiKX0sIAogICAgICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIHsgCiAgICAgICAgICAgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpfSwgCiAgICAgICAgIGZpbmFsbHkgPSBsaWJyYXJ5KCJnZ3Bsb3QyIikpCgpvcHRpb25zKGtuaXRyLnRhYmxlLmZvcm1hdCA9ICJodG1sIikKYGBgCgojIEludHJvZHVjdGlvbgoKQnVsayBSTkEgc2VxdWVuY2luZyBkYXRhIG9uIDI0IHByZS10cmVhdG1lbnQgYnJlYXN0IGNhbmNlciB0dW1vdXJzIHBlcmZvcm1lZCBieSBXdSBldCBhbC4gW0B3dTIwMjFzaW5nbGVdIHdhcyBkb3dubG9hZGVkIGZyb20gYEdFT2Agd2l0aCBhY2Nlc3Npb24gW0dTRTE3NjA3OF0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9nZW8vcXVlcnkvYWNjLmNnaT9hY2M9R1NFMTc2MDc4KSwgYW5kIFthc3NvY2lhdGVkIHB1YmxpY2F0aW9uXShodHRwczovL3BtYy5uY2JpLm5sbS5uaWguZ292L2FydGljbGVzL1BNQzkwNDQ4MjMvKS4KCmBgYHtyfQpnZW9faWQgPC0gIkdTRTE3NjA3OCIKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpnc2UgPC0gZ2V0R0VPKGdlb19pZCwgR1NFTWF0cml4PUZBTFNFKQpncGwgPC0gbmFtZXMoZ3NlQGdwbHMpCmdwbF9pbmZvIDwtIE1ldGEoZ2V0R0VPKGdwbCkpCmBgYAoKVGhpcyBkYXRhc2V0IHdhcyBzZXF1ZW5jZWQgdXNpbmcgYHIgZ3BsX2luZm8kdGl0bGVgLCBzdWJtaXR0ZWQgb24gYHIgZ3BsX2luZm8kc3VibWlzc2lvbl9kYXRlYC4KCkJyZWFzdCBjYW5jZXJzIGFyZSBjbGluaWNhbGx5IHN0cmF0aWZpZWQgYmFzZWQgb246CgotIGV4cHJlc3Npb24gb2YgdGhlIGVzdHJvZ2VuIHJlY2VwdG9yICgqRVIqKSwgCi0gZXhwcmVzc2lvbiBvZiB0aGUgcHJvZ2VzdGVyb25lIHJlY2VwdG9yICgqUFIqKSwgYW5kCi0gb3ZlcmV4cHJlc3Npb24gb2YgKkhFUjIqIChvciBhbXBsaWZpY2F0aW9uIG9mICpIRVIyKiBnZW5lICpFUkJCMiopCgpUaGlzIHJlc3VsdHMgaW4gdGhlIGZvbGxvd2luZyB0aHJlZSBfX2NsaW5pY2FsIHN1YnR5cGVzX18gd2l0aGluIHRoaXMgZGF0YXNldDoKCi0gTHVtaW5hbCBpZS4gRVIrOyAoKkVSKyosICpQUisvLSopCi0gSEVSMis7ICgqSEVSMisqLCAqRVIrLy0qLCAqUFIrLy0qKQotIFRyaXBsZSBOZWdhdGl2ZSBpZS4gVE5CQzsgKCpFUi0qLCAqUFItKiwgKkhFUjItKikKCkJyZWFzdCBjYW5jZXJzIGFyZSBhbHNvIHN0cmF0aWZpZWQgb24gYnVsayB0cmFuc2NyaXB0b21pYyBwcm9maWxpbmcgdmlhIFBBTTUwIGdlbmUgc2lnbmF0dXJlcyBbQHBhcmtlcjIwMDlzdXBlcnZpc2VkXSBkZXNjcmliaW5nIGZpdmUgX19tb2xlY3VsYXIgc3VidHlwZXNfXzogTHVtaW5hbCBBLCBMdW1pbmFsIEIsIEhFUjItZW5yaWNoZWQsIEJhc2FsLWxpa2UsIGFuZCBOb3JtYWwtbGlrZS4KClRoZSB+NzAtODAlIGNvbmNvcmRhbmNlIGJldHdlZW4gY2xpbmljYWwgYW5kIG1vbGVjdWxhciBzdWJ0eXBlcyBtb3RpdmF0ZWQgdGhpcyBzdHVkeSB0byBpbXByb3ZlIGZ1bmN0aW9uYWwgdW5kZXJzdGFuZGluZyBvZiBicmVhc3QgY2FuY2VyIGluIGEgYnJvYWRlciBhbmQgbW9yZSBjb2hlcmVudCBzZW5zZS4KCkZvciB0aGlzIHN0dWR5LCB0aGUgY2xpbmljYWwgc3VidHlwZSBjb25kaXRpb25zIGNsYXNzaWZpZWQgYXJlIGFzIGZvbGxvd3M6CgotIGBIRVIyK2AgOyAoKkhFUjIrKiwgKkVSLSosICpQUisvLSopCi0gYEhFUjIrL0VSK2AgOyAoKkhFUjIrKiwgKkVSKyosICpQUisvLSopCi0gYEVSK2AgOyAoKkhFUjItKiwgKkVSKyosICpQUisvLSopCi0gYFROQkNgIDsgKCpIRVIyLSosICpFUi0qLCAqUFItKikKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQpub3JtYWxpemVkX2NvdW50cyA8LSByZWFkLnRhYmxlKAogIGZpbGU9ZmlsZS5wYXRoKGdldHdkKCksIGdlb19pZCwKICAgICAgICAgICAgICAgICBwYXN0ZShnZW9faWQsIAogICAgICAgICAgICAgICAgICAgICAgICJub3JtYWxpemVkX2NvdW50cy50eHQiLCAKICAgICAgICAgICAgICAgICAgICAgICBzZXA9Il8iKSksCiAgaGVhZGVyPVRSVUUsIHNlcD0iXHQiLCAKICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFLCAKICBjaGVjay5uYW1lcz1GQUxTRSkKYGBgCgpUaGUgZGlzdHJpYnV0aW9uIG9mIGNsaW5pY2FsIHN1YnR5cGVzIGFjcm9zcyB0aGUgMjQgc2FtcGxlcyBpcyBzaG93biBpbiB0YWJsZSAxLgoKYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KdHlwZXMgPC0gZG8uY2FsbChyYmluZCwKICAgICAgICAgICAgICAgICBsYXBwbHkoZ3NlQGdzbXMsLAogICAgICAgICAgICAgICAgICAgICAgICBGVU49ZnVuY3Rpb24oeCwgLi4uKXsKICAgICAgICAgICAgICAgICAgICAgICAgICBjKHhAaGVhZGVyJHRpdGxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgeEBoZWFkZXIkY2hhcmFjdGVyaXN0aWNzX2NoMSl9KSlbLGMoMSwyKV0KdHlwZXNbLDJdIDwtIGdzdWIodHlwZXNbLDJdLAogICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gImNsaW5pY2FsX3N1YnR5cGU6ICIsCiAgICAgICAgICAgICAgICAgIHJlcGxhY2VtZW50ID0gIiIpCgpwcmVzZW50IDwtIGNvbG5hbWVzKG5vcm1hbGl6ZWRfY291bnRzKQp0eXBlcyA8LSB0eXBlc1t3aGljaCh0eXBlc1ssMV0gJWluJSBwcmVzZW50KSxdCgp0eXBlcyA8LSBjYmluZCh0eXBlcywgZ3JlcGwoIl5bSF1bRV1bUl1bMl1bK10iLCB0eXBlc1ssMl0pKQp0eXBlcyA8LSBjYmluZCh0eXBlcywgZ3JlcGwoIltFXVtSXVsrXSQiLCB0eXBlc1ssMl0pKQpjb2xuYW1lcyh0eXBlcykgPC0gYygic2FtcGxlIiwgInN1YnR5cGUiLCAiaGVyMiIsICJlciIpCnR5cGVzX2RmIDwtIGFzLmRhdGEuZnJhbWUodHlwZXMpCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KaGVyMiA9IGxlbmd0aCh3aGljaCh0eXBlc1ssInN1YnR5cGUiXSA9PSAiSEVSMisiKSkKaGVyMmVyID0gbGVuZ3RoKHdoaWNoKHR5cGVzWywic3VidHlwZSJdID09ICJIRVIyKy9FUisiKSkKdG5iYyA9IGxlbmd0aCh3aGljaCh0eXBlc1ssInN1YnR5cGUiXSA9PSAiVE5CQyIpKQplciA9IGxlbmd0aCh3aGljaCh0eXBlc1ssInN1YnR5cGUiXSA9PSAiRVIrIikpCnRvdGFsID0gc3VtKGhlcjIsIGhlcjJlciwgdG5iYywgZXIpCgpzdWJ0eXBlX2NvdW50cyA9IGRhdGEuZnJhbWUoYyhoZXIyLCBoZXIyZXIsIHRuYmMsIGVyLCB0b3RhbCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXMgPSBjKCJIRVIyKyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSEVSMisvRVIrIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUTkJDIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFUisiLCAiVG90YWwiKSkKc3VidHlwZV9jb3VudHMkcGVyY2VudGFnZXMgPSBzdWJ0eXBlX2NvdW50c1ssMV0gKiAxMDAgLyB0b3RhbApgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30Kc3VidHlwZV9jb3VudHMgJT4lCiAga25pdHI6OmthYmxlKGNhcHRpb249IlRhYmxlIDE6IENsaW5pY2FsIGJyZWFzdCBjYW5jZXIgc3VidHlwZSBzcGxpdHMgaW4gb3VyIGRhdGFzZXQiLCAKICAgICAgZGlnaXRzPTIsCiAgICAgIGNvbC5uYW1lcz1jKCJDb3VudCIsICJQZXJjZW50IikpICU+JQogIGthYmxlX3N0eWxpbmcoKSAlPiUKICByb3dfc3BlYyg1LCBib2xkID0gVCkKYGBgCgpUaGlzIGxlYWRzIHRvIGByIDQwMC8yNGAlIG9mIHNhbXBsZXMgY29udGFpbmluZyBgSEVSMmAgZXhwcmVzc2lvbiwgYW5kIGByIDEwMDAvMjRgJSBvZiBzYW1wbGVzIGNvbnRhaW5pbmcgYEVSYCBleHByZXNzaW9uLCB3aXRoIHRoZSBvdmVybGFwcyBvZiB0aGVzZSByZXByZXNlbnRpbmcgYHIgMjAwLzI0YCUgb2YgYWxsIHNhbXBsZXM7IGByIDIwMC80YCUgb2YgdGhvc2Ugd2l0aCBgSEVSMmAsIGByIDIwMC8xNGAlIG9mIHRob3NlIHdpdGggYEVSYC4KClRoZSByYXcgY291bnRzIHdlcmUgY2xlYW5lZCwgbWFwcGVkIHRvIFtIVUdPIEdlbmUgTm9tZW5jbGF0dXJlIENvbW1pdHRlZSAoSEdOQykgU3ltYm9sc10oaHR0cHM6Ly93d3cuZ2VuZW5hbWVzLm9yZy8pLCBhbmQgbm9ybWFsaXplZCB0byBwcm9kdWNlIGZpbmFsIGNvdW50cyB3aGljaCB3aWxsIGJlIHVzZWQgZm9yIHRoZSBkdXJhdGlvbiBvZiB0aGlzIHJlcG9ydC4KCk9mIHRoZSBvcmlnaW5hbCBgNTgzODdgIGdlbmVzLCB3ZSB3ZXJlIGFibGUgdG8gbWFwIGFuZCBwcm9kdWNlIGAyODcxMmAgdW52ZXJzaW9uZWQsIHVuaXF1ZSBnZW5lcywgb2Ygd2hpY2ggZmlsdGVyaW5nIG91dGxpZXJzIChrZWVwaW5nIGdlbmVzIHByZXNlbnQgaW4gYSBtaW5pbXVtIG9mIGAxMmAgc2FtcGxlcykgcmVzdWx0ZWQgaW4gYDE0ODAwYCBnZW5lcyByZW1haW5pbmcuIFRoaXMgcmVzdWx0cyBpbiB0aGUgZm9sbG93aW5nIHBsb3RzLgoKVGhlIGRlbnNpdHkgcGxvdCBzaG93cyB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBjbGVhbmVkLCBmaWx0ZXJlZCwgYW5kIG5vcm1hbGl6ZWQgY291bnRzIHBlciBtaWxsaW9uIGFjcm9zcyBhbGwgc2FtcGxlcyAodmFyeWluZyBjb2xvdXJzKS4gSXQgZGlzcGxheXMgYSBzbW9vdGggY3VydmUgYXMgdGhlIHJlc3VsdCBvZiBvdXIgcHJlLXByb2Nlc3NpbmcuCgo8YnIvPgoKIVtGaWd1cmUgMTogRGVuc2l0eSBvZiBtaW5pbXVtIDEyIHNhbXBsZXMgZmlsdGVyZWQgYW5kIG5vcm1hbGl6ZWQgQ1BNIGNvdW50cyBmb3IgMjQgc2FtcGxlcyBhY3Jvc3MgZm91ciBjbGluaWNhbCBzdWJ0eXBlcyBvZiBicmVhc3QgY2FuY2VyIHRpc3N1ZV0oL2hvbWUvcnN0dWRpby9wcm9qZWN0cy9maWd1cmVzL0dTRTE3NjA3OF9maWx0X25vcm1fZGVuc2l0eS5wbmcpCgo8YnIvPgpEaXNwZXJzaW9uIHdhcyBjYWxjdWxhdGVkIHVzaW5nIGBlZGdlUmAgdG8gZGVzY3JpYmUgZGV2aWF0aW9uIG9mIHZhcmlhbmNlIGZyb20gdGhlIG1lYW4uIFRoZSBCaW9sb2dpY2FsIENvZWZmaWNpZW50IG9mIFZhcmlhdGlvbiAoQkNWKSBpcyBkaXNwZXJzaW9uLXNxdWFyZWQsIGFuZCByZXByZXNlbnRzIHRoZSBtZWFuLXZhcmlhbmNlIHJlbGF0aW9uc2hpcCBhbW9uZyBnZW5lcy4KCiFbRmlndXJlIDI6IEJpb2xvZ2ljYWwgQ29lZmZpY2llbnQgb2YgVmFyaWF0aW9uIChEaXNwZXJzaW9uIHNxdWFyZWQpIGZvciAyNCBzYW1wbGVzIGFjcm9zcyBmb3VyIGNsaW5pY2FsIHN1YnR5cGVzIG9mIGJyZWFzdCBjYW5jZXIgdGlzc3VlIGdlbmUtd2lzZV0oL2hvbWUvcnN0dWRpby9wcm9qZWN0cy9maWd1cmVzL0dTRTE3NjA3OF9iY3YucG5nKQoKPGJyLz4KClRoZSBub3JtYWxpemVkIGNvdW50cyBpbml0aWFsaXplZCBhYm92ZSBhcmUgZm9ybWF0dGVkIGFzIHNob3duIGJ5IHRoZSBzdWJzZWN0aW9uIGRpc3BsYXllZCBpbiB0YWJsZSAyLgoKYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQpoZWFkKG5vcm1hbGl6ZWRfY291bnRzWzE6NV0pICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSAyOiBGb3JtYXQgb2YgTm9ybWFsaXplZCBjb3VudHMgZGF0YXNldCBhcyBkZXNjcmliZWQgYWJvdmUiLCBkaWdpdHM9NCkgJT4lCiAga2FibGVfc3R5bGluZygpCmBgYAoKIyBEaWZmZXJlbnRpYWwgR2VuZSBFeHByZXNzaW9uCgpHaXZlbiBvdXIgbm9ybWFsaXplZCBleHByZXNzaW9uIGRhdGFzZXQgY29udGFpbnMgb25seSBncm91cGVkIGNsYXNzaWZpY2F0aW9uIHZpYSBjbGluaWNhbCBzdWJ0eXBlcywgdGhlc2UgYXJlIHRoZSBvYnZpb3VzIGNob2ljZSBmb3IgZmFjdG9ycy4gQnV0LCBkdWUgdG8gdGhlIG5hdHVyZSBvZiB0aGVzZSBjbGFzc2lmaWVycywgdGhlIG5hbWVzIHRoZW1zZWx2ZXMgcmVwcmVzZW50IGJpbmFyeSBwYWlyaW5nIG9mIGBIRVIyYCBhbmQgYEVSYCBleHByZXNzaW9uIGFuZCBhYnNlbmNlIChpbiBhIGNsaW5pY2FsIHNldHRpbmcpLiBUaGlzIHByb3ZpZGVzIHNvbWUgZmxleGliaWxpdHkgZm9yIGFuYWx5emluZyBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBzaW5jZSB3ZSByZWFsbHkgaGF2ZSB0d28gcHJvdGVpbiBleHByZXNzaW9ucywgd2l0aCB0aGVpciBiaW5hcnkgcGFpcmluZyBhcyB0aGUgY2xpbmljYWwgc3VidHlwZSBjbGFzc2lmaWNhdGlvbi4KClRoZSBNdWx0aS1EaW1lbnNpb25hbCBTY2FsaW5nIChNRFMpIHBsb3Qgd2FzIHByb2R1Y2VkIHVzaW5nIGBsaW1tYWAgb24gdGhlIG5vcm1hbGl6ZWQgZGF0YSwgYW5kIGl0IHNob3dzIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHNhbXBsZXMgZmFjdG9yZWQgYnkgdGhlIGZvdXIgZGlzdGluY3QgY2xpbmljYWwgc3VidHlwZXMuCjxici8+CgpgYGB7ciBtZHMtc3VidHlwZSwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD01LCBmaWcuY2FwPSJGaWd1cmUgMzogTXVsdGktRGltZW5zaW9uYWwgU2NhbGluZyBwbG90IGZvciBjbGluaWNhbCBzdWJ0eXBlcyBvZiBicmVhc3QgY2FuY2VyIGFzIGNsYXNzaWZpY2F0aW9ucyBvZiBvdmVyZXhwcmVzc2lvbiwgb3IgbGFjayB0aGVyZW9mLCBvZiBFUiBhbmQgSEVSMiJ9Cm5vcm1fbWF0cml4IDwtIGFzLm1hdHJpeChub3JtYWxpemVkX2NvdW50cykKCmxpbW1hOjpwbG90TURTKG5vcm1fbWF0cml4LCBsYWJlbHM9TlVMTCwgcGNoPTEsCiAgICAgICAgICAgICAgIGNvbCA9IGMoImJsdWUiLCAicmVkIiwgCiAgICAgICAgICAgICAgICAgICAgICAgInB1cnBsZSIsICJncmVlbiIpW2ZhY3Rvcih0eXBlc19kZiRzdWJ0eXBlKV0pCnRpdGxlKCJGaWd1cmUgMzogTURTIHBsb3Qgb2YgY2xpbmljYWwgc3VidHlwZXMgb2YgYnJlYXN0IGNhbmNlciIpCmxlZ2VuZCgidG9wbGVmdCIsCiAgICAgICBsZWdlbmQ9bGV2ZWxzKGZhY3Rvcih0eXBlc19kZiRzdWJ0eXBlKSksCiAgICAgICBwY2g9YygxKSwgY29sPWMoImJsdWUiLCAicmVkIiwgInB1cnBsZSIsICJncmVlbiIpLAogICAgICAgdGl0bGUgPSAiQ2xpbmljYWwgc3VidHlwZSIsIGJ0eT0nbicsIGNleD0wLjc1KQpgYGAKCgpJbiB0aGUgZ2l2ZW4gTURTIHBsb3QsIG5vdGljZSB0aGF0IGBibHVlYCBhbmQgYHJlZGAgYXJlIG9wcG9zaXRlcyAoYCsvLWAgYW5kIGAtLytgKSwgYHB1cnBsZWAgaXMgdGhlIGludGVybWVkaWFyeSBiZXR3ZWVuIGBibHVlYCBhbmQgYHJlZGAgKGArLytgKSwgd2hlcmVhcyBgZ3JlZW5gIHJlcHJlc2VudHMgYFROQkNgOiBkb3VibGUgbmVnYXRpdmUgKGAtLy1gKS4gQWx0aG91Z2ggcHJvZ2VzdGVyb25lIGlzIGEgbWFya2VyIGZvciBicmVhc3QgY2FuY2VyLCBpdHMgZXhwcmVzc2lvbiBpcyBub3QgcXVhbnRpZmlhYmx5IHByZXNlbnQgd2l0aGluIHRoZSBkYXRhc2V0LCBhbmQgc28gaXMgbm90IGluY2x1ZGVkLiBIb3dldmVyLCBgVE5CQ2AgaW1wbGllcyBgUFJgIGlzIG5vdCBvdmVybHkgZXhwcmVzc2VkIGFzIHdlbGwuCgpJbiB0ZXJtcyBvZiB0aGVzZSBjb2xvdXJzIGluIHJlbGF0aW9uIHRvIGVhY2ggb3RoZXIsIHlvdSBjYW4gc2VlIHNvbWUgY2x1c3RlcmluZyBhcHBlYXJpbmcsIGFsdGhvdWdoIG5vdGhpbmcgaXMgY29uZmlkZW50bHkgZGlzdGluY3QuCgojIyBDYWxjdWxhdGUgcC12YWx1ZXMgZm9yIGVhY2ggZ2VuZS4gCgpJIHJlZGVmaW5lIHRoZSBtb2RlbCB0byBpbmNsdWRlIHRoZSBjbGluaWNhbCBzdWJ0eXBlcyBvZiBicmVhc3QgY2FuY2VyIGFzIGZhY3RvcnMsIGJvdGggYXMgZm91ciBzZXBhcmF0ZSBjbGFzc2lmaWVycywgYW5kIHRoZSBiaW5hcnkgcGFpcmluZyBvZiBvdmVyL3VuZGVyIGV4cHJlc3Npb24gb2YgYEhFUjJgIGFuZCBgRVJgLgoKYGBge3J9CiMgYWdncmVnYXRlIG1vZGVsIGRlc2lnbgptb2RlbF9kZXNpZ24gPC0gbW9kZWwubWF0cml4KH4gdHlwZXNfZGYkc3VidHlwZSkKCiMgc3BsaXQgbW9kZWwgZGVzaWduIChiaW5hcnkgcGFpcnMpCnNwbHRfbW9kZWxfZGVzaWduIDwtIG1vZGVsLm1hdHJpeCh+IHR5cGVzX2RmJGhlcjIgKyB0eXBlc19kZiRlcikKYGBgCgpHaXZlbiBib3RoIGRlc2lnbiBjaG9pY2VzLCBJIHVzZWQgYGVkZ2VSYCdzIGBRdWFzaSBsaWtlbGlob29kIG1vZGVsYCB0byBjcmVhdGUgcXVhc2ktbGlrZWxpaG9vZCBmaXRzLgoKYGBge3J9CiMgbm9ybWFsaXplZCBjb3VudHMgZ3JvdXBlZCBieSBjbGluaWNhbCBzdWJ0eXBlCmQgPC0gREdFTGlzdChjb3VudHM9bm9ybV9tYXRyaXgsIAogICAgICAgICAgICAgZ3JvdXA9dHlwZXNfZGYkc3VidHlwZSkKCiMgZXN0aW1hdGUgZGlzcGVyc2lvbiBvbiBzdWJ0eXBlIG1vZGVsIGRlc2lnbgpkXyA8LSBlc3RpbWF0ZURpc3AoZCwgbW9kZWxfZGVzaWduKQpxbGZpdCA8LSBnbG1RTEZpdChkXywgbW9kZWxfZGVzaWduKQoKIyBpbiBwYXJhbGxlbCwgZXN0aW1hdGUgZGlzcGVyc2lvbiBvbiBiaW5hcnkgcGFpcmluZyBtb2RlbCBkZXNpZ24KZF9zcGx0IDwtIGVzdGltYXRlRGlzcChkLCBzcGx0X21vZGVsX2Rlc2lnbikKcWxmaXRfc3BsdCA8LSBnbG1RTEZpdChkX3NwbHQsIHNwbHRfbW9kZWxfZGVzaWduKQpgYGAKCk5vdywgd2UgY2FuIHVzZSBgZ2xtUUxGVGVzdGAgdG8gY2FsY3VsYXRlIHRoZSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhY2NvcmRpbmcgdG8gdGhpcyBtb2RlbC4KCmBgYHtyfQojIGZpdCBzdWJ0eXBlIG1vZGVsIGRlc2lnbgpxbGYuc3VidHlwZXMgPC0gZ2xtUUxGVGVzdChxbGZpdCkKYGBgCgpgYGB7cn0KIyBmaXQgc3BsaXQgbW9kZWwgZGVzaWduCnFsZi5oZXIycCA8LSBnbG1RTEZUZXN0KHFsZml0X3NwbHQsIAogICAgICAgICAgICAgICAgICAgICAgICBjb2VmPSd0eXBlc19kZiRlclRSVUUnKQpxbGYuZXJwIDwtIGdsbVFMRlRlc3QocWxmaXRfc3BsdCwgCiAgICAgICAgICAgICAgICAgICAgICBjb2VmPSd0eXBlc19kZiRoZXIyVFJVRScpCmBgYAoKQXQgdGhpcyBwb2ludCwgd2UgYW5hbHl6ZSB0aGUgY2FsY3VsYXRlZCBwLXZhbHVlcyBhbmQgYWdncmVnYXRlIG91ciB0b3AgaGl0cyBmb3IgZWFjaCBtb2RlbC4KCmBgYHtyfQojIHRvcCB0YWdzIGZvciBhZ2dyZWdhdGUgbW9kZWwgZGVzaWduCnRvcF9oaXRzIDwtIHRvcFRhZ3MocWxmLnN1YnR5cGVzLCAKICAgICAgICAgICAgICAgICAgICBzb3J0LmJ5ID0gIlBWYWx1ZSIsCiAgICAgICAgICAgICAgICAgICAgbiA9IG5yb3cobm9ybWFsaXplZF9jb3VudHMpKQoKIyB0b2cgdGFncyBmb3Igc3BsaXQgbW9kZWwgZGVzaWduCnRvcF9oZXIycCA8LSB0b3BUYWdzKHFsZi5oZXIycCwKICAgICAgICAgICAgICAgICAgICAgc29ydC5ieSA9ICJQVmFsdWUiLAogICAgICAgICAgICAgICAgICAgICBuID0gbnJvdyhub3JtYWxpemVkX2NvdW50cykpCnRvcF9lcnAgPC0gdG9wVGFncyhxbGYuZXJwLAogICAgICAgICAgICAgICAgICAgc29ydC5ieSA9ICJQVmFsdWUiLAogICAgICAgICAgICAgICAgICAgbiA9IG5yb3cobm9ybWFsaXplZF9jb3VudHMpKQpgYGAKCiMjIyBIb3cgbWFueSBnZW5lcyB3ZXJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkPwoKYGBge3IsIGVjaG89RkFMU0V9CiMgbGVuZ3RoKHdoaWNoKHRvcF9oaXRzJHRhYmxlJFBWYWx1ZSA8IDAuMDUpKQojIGxlbmd0aCh3aGljaCh0b3BfaGVyMnAkdGFibGUkUFZhbHVlIDwgMC4wNSkpCiMgbGVuZ3RoKHdoaWNoKHRvcF9wZXJwJHRhYmxlJFBWYWx1ZSA8IDAuMDUpKQpgYGAKCkZvciBvdXIgdGhyZWUgbW9kZWwgZGVzaWducyAob25lIGFnZ3JlZ2F0ZSwgYW5kIHR3byBiaW5hcnkgc3BsaXRzKSwgdGhlIGZvbGxvd2luZyBudW1iZXIgb2YgZ2VuZXMgd2VyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBiZWZvcmUgY29ycmVjdGlvbi4KCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuY2FwPSJUYWJsZSAzOiBOdW1iZXIgb2YgUC1WYWx1ZXMgdGhhdCBhcmUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQsIGllLiA8IDAuMDUsIGZvciB0aGUgdGhyZWUgZGlmZmVyZW50IG1vZGVsIGRlc2lnbnMifQpwdmFsc19kZiA8LSBkYXRhLmZyYW1lKAogIGMobGVuZ3RoKHdoaWNoKHRvcF9oaXRzJHRhYmxlJFBWYWx1ZSA8IDAuMDUpKSwKICAgIGxlbmd0aCh3aGljaCh0b3BfaGVyMnAkdGFibGUkUFZhbHVlIDwgMC4wNSkpLAogICAgbGVuZ3RoKHdoaWNoKHRvcF9lcnAkdGFibGUkUFZhbHVlIDwgMC4wNSkpKSwKICByb3cubmFtZXMgPSBjKCJBZ2dyZWdhdGUgYWNyb3NzIHN1YnR5cGVzIiwgIkhFUjIgZXhwcmVzc2lvbiIsICJFUiBleHByZXNzaW9uIikKKQoKcHZhbHNfZGYgJT4lCiAga25pdHI6OmthYmxlKGNhcHRpb249IlRhYmxlIDM6IE51bWJlciBvZiBQLVZhbHVlcyB0aGF0IGFyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBmb3IgdGhlIHRocmVlIGRpZmZlcmVudCBtb2RlbCBkZXNpZ25zIiwKICAgICAgICAgICAgICAgY29sLm5hbWVzPWMoIlNpZ25pZmljYW50bHkgRGlmZmVyZW50aWFsbHkgRXhwcmVzc2VkIEdlbmVzIikpICU+JQogIGthYmxlX3N0eWxpbmcoKQpgYGAKCiMjIyBXaGF0IHRocmVzaG9sZHMgZGlkIHlvdSB1c2UgYW5kIHdoeT8KCkEgdGhyZXNob2xkIG9mIGAwLjA1YCBmb3IgcC12YWx1ZXMgaXMgdmVyeSBzdGFuZGFyZC4gSXQgaW1wbGllcyB0aGF0IHN0YXRpc3RpY2FsbHkgd2Ugd2lsbCBvbmx5IGFjaGlldmUgdGhpcyBvdXRjb21lIGA1YCUgb2YgdGhlIHRpbWUgYXNzdW1pbmcgdGhlIG51bGwgaHlwb3RoZXNpcyBpcyB0cnVlIChvdXIgbnVsbCBoeXBvdGhlc2lzIGJlaW5nIHRoYXQgdGhlcmUgaXMgbm8gZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYmV0d2VlbiB0aGUgY2xpbmljYWwgc3VidHlwZXMgaW4gdGhlc2UgZ2VuZXMpLgoKSWYgSSBjb250aW51ZWQgdGhpcyBhbmFseXNpcyBhbmQgZm91bmQgdGhhdCBJIGhhZCBhIGxvdCBvZiBnZW5lcyByZW1haW5pbmcsIEkgY291bGQgbG93ZXIgdGhlIHRocmVzaG9sZCwgYnV0IGAwLjA1YCBpcyBhIHNvbGlkIHN0YXJ0aW5nIHBvaW50IHdpdGggdGhhdCBpbiBtaW5kLgoKIyMgTXVsdGlwbGUgaHlwb3RoZXNpcyB0ZXN0aW5nCgpgZWRnZVJgJ3MgYW5hbHlzaXMgcHJvdmlkZXMgYSBgRkRSYCB2YWx1ZSwgd2hpY2ggaW1wbGllcyBCZW5qYW1pbmktSG9jaGJlcmcsIGhvd2V2ZXIgSSB3YW50ZWQgdG8gaW5kZXBlbmRlbnRseSB2ZXJpZnkuCgpgYGB7cn0KY29ycmVjdGVkX3RvcF9oaXRzIDwtIHAuYWRqdXN0KHRvcF9oaXRzJHRhYmxlJFBWYWx1ZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiQkgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG4gPSBucm93KG5vcm1hbGl6ZWRfY291bnRzKSkKbGVuZ3RoKHdoaWNoKGNvcnJlY3RlZF90b3BfaGl0cyA8IDAuMDUpKQpgYGAKClNvLCB1c2luZyB0aGlzIGNvcnJlY3Rpb24gbWV0aG9kLCBvbmx5IDMgZ2VuZXMgcGFzcyBjb3JyZWN0aW9uIGZvciBzaWduaWZpY2FudCBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbi4KCiMjIyBXaGljaCBtZXRob2QgZGlkIHlvdSB1c2U/IGFuZCB3aHk/CgpBcyBkZXNjcmliZWQsIHRoZSBGYWxzZSBEaXNjb3ZlcnkgUmF0ZXMgcHJvdmlkZWQgYnkgb3VyIGFuYWx5c2lzIG1hdGNoIG15IGluZGVwZW5kZW50IHVuZGVyc3RhbmRpbmcgb2YgdGhlIF9fQmVuamFtaW5pLUhvY2hiZXJnX18gbWV0aG9kLiAKClRoaXMgbWV0aG9kIGlzIHZlcnkgYXBwbGljYWJsZSB0byBvdXIgdXNlLWNhc2Ugc2luY2UgaXQgaXMgbGVzcyBzdHJpbmdlbnQgdGhhbiBCb25mZXJyb25pIHdoZW4gaXQgY29tZXMgdG8gaGF2aW5nIGEgbGFyZ2UgbnVtYmVyIG9mIGh5cG90aGVzZXMuIEl0IGlzIGJlc3QgcHJhY3RpY2UgdG8gdXNlIEJlbmphbWluaS1Ib2NoYmVyZyBmaXJzdCB0byBzZWUgd2hpY2ggb2YgeW91ciBnZW5lcyBwYXNzIGNvcnJlY3Rpb24sIGFuZCBpZiB5b3UgbmVlZCBhIG1vcmUgc3RyaW5nZW50IGNvcnJlY3RpdmUgbWV0aG9kLCB5b3UgY2FuIGNvbnNpZGVyIHVzaW5nIEJvbmZlcnJvbmkuIEhvd2V2ZXIsIEJvbmZlcnJvbmkgaXMgc2FpZCB0byBiZSBtb3JlIHVzZWZ1bCB3aGVuIHlvdSBhcmUgdGVzdGluZyBhIHNtYWxsZXIgbnVtYmVyIG9mIGh5cG90aGVzZXMgd2hpY2ggaXMgZ2VuZXJhbGx5IG5vdCB0aGUgY2FzZSBmb3IgUk5BIHNlcXVlbmNpbmcgZGF0YS4KCiMjIyBIb3cgbWFueSBnZW5lcyBwYXNzZWQgY29ycmVjdGlvbj8KCkZvciBvdXIgdHdvIG1vZGVsIGRlc2lnbnMsIHRoZSBmb2xsb3dpbmcgbnVtYmVyIG9mIGdlbmVzIHBhc3NlZCBjb3JyZWN0aW9uIGZvciBlYWNoIGNsYXNzaWZpZXIuCgpgYGB7ciwgZWNobz1GQUxTRX0KIyBsZW5ndGgod2hpY2godG9wX2hpdHMkdGFibGUkRkRSIDwgMC4wNSkpCiMgbGVuZ3RoKHdoaWNoKHRvcF9oZXIycCR0YWJsZSRGRFIgPCAwLjA1KSkKIyBsZW5ndGgod2hpY2godG9wX2VycCR0YWJsZSRGRFIgPCAwLjA1KSkKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmNhcD0iVGFibGUgNDogTnVtYmVyIG9mIFAtVmFsdWVzIHRoYXQgYXJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkLCBpZS4gPCAwLjA1LCBiZWZvcmUgYW5kIGFmdGVyIEJlbmphbWluaS1Ib2NoYmVyZyBjb3JyZWN0aW9uIGZvciB0aGUgdGhyZWUgZGlmZmVyZW50IG1vZGVsIGRlc2lnbnMifQpwdmFsc19kZiA8LSBkYXRhLmZyYW1lKAogIGMobGVuZ3RoKHdoaWNoKHRvcF9oaXRzJHRhYmxlJFBWYWx1ZSA8IDAuMDUpKSwKICAgIGxlbmd0aCh3aGljaCh0b3BfaGVyMnAkdGFibGUkUFZhbHVlIDwgMC4wNSkpLAogICAgbGVuZ3RoKHdoaWNoKHRvcF9lcnAkdGFibGUkUFZhbHVlIDwgMC4wNSkpKSwKICByb3cubmFtZXMgPSBjKCJBZ2dyZWdhdGUgYWNyb3NzIHN1YnR5cGVzIiwgIkhFUjIgZXhwcmVzc2lvbiIsICJFUiBleHByZXNzaW9uIikKKQpwdmFsc19kZiA8LSBjYmluZChwdmFsc19kZiwgCiAgICAgICAgICAgICAgICAgIGMobGVuZ3RoKHdoaWNoKHRvcF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUpKSwKICAgICAgICAgICAgICAgICAgICBsZW5ndGgod2hpY2godG9wX2hlcjJwJHRhYmxlJEZEUiA8IDAuMDUpKSwKICAgICAgICAgICAgICAgICAgICBsZW5ndGgod2hpY2godG9wX2VycCR0YWJsZSRGRFIgPCAwLjA1KSkpKQoKcHZhbHNfZGYgJT4lCiAga25pdHI6OmthYmxlKGNhcHRpb249IlRhYmxlIDQ6IE51bWJlciBvZiBQLVZhbHVlcyB0aGF0IGFyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBmb3IgdGhlIHRocmVlIGRpZmZlcmVudCBtb2RlbCBkZXNpZ25zIiwKICAgICAgICAgICAgICAgY29sLm5hbWVzPWMoIlNpZ25pZmljYW50bHkgRGlmZmVyZW50aWFsbHkgRXhwcmVzc2VkIEdlbmVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJTaWduaWZpY2FudGx5IERpZmZlcmVudGlhbGx5IEV4cHJlc3NlZCBHZW5lcyBhZnRlciBjb3JyZWN0aW9uIikpICU+JQogIGthYmxlX3N0eWxpbmcoKQpgYGAKClRoZXJlIGlzIGNsZWFybHkgYSBsYXJnZSByZWR1Y3Rpb24gaW4gbnVtYmVyIG9mIGdlbmVzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkLgoKRm9yIHRoZSBhZ2dyZWdhdGUgbW9kZWwgb2YgY2xpbmljYWwgc3VidHlwZXMsIG9ubHkgYDNgIGdlbmVzIHBhc3NlZCBjb3JyZWN0aW9uIGZvciBmYWxzZSBkaXNjb3ZlcnkuIF9fTm9fXyBnZW5lcyBwYXNzZWQgY29ycmVjdGlvbiBmb3IgYEhFUjJgIGV4cHJlc3Npb24gYXNzb2NpYXRpb24sIHdoZXJlYXMgYDExYCBnZW5lcyBwYXNzZWQgY29ycmVjdGlvbiBmb3IgYEVSYCBleHByZXNzaW9uIGFzc29jaWF0aW9uLgoKVGhlIGdlbmVzIGFuZCB0aGVpciBhc3NvY2lhdGVkIHZhbHVlcyBhcmUgc2hvd24gaW4gdGhlIHRhYmxlcyBiZWxvdy4KCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuY2FwPSJUYWJsZSA1OiBHZW5lcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBhZnRlciBjb3JyZWN0aW9uIGFjcm9zcyBjbGluaWNhbCBzdWJ0eXBlcywgYWdncmVnYXRlIGRlc2lnbiJ9CnRvcF9oaXRzJHRhYmxlW3RvcF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUsXQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuY2FwPSJUYWJsZSA2OiBHZW5lcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBhZnRlciBjb3JyZWN0aW9uIGFzc29jaWF0ZWQgd2l0aCBFUiBvdmVyZXhwcmVzc2lvbiJ9CnRvcF9lcnAkdGFibGVbdG9wX2VycCR0YWJsZSRGRFIgPCAwLjA1LF0KYGBgCgojIyBBbW91bnQgb2YgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzCgojIyMgTUEgUGxvdAoKQW4gTUEgUGxvdCBkZW1vbnN0cmF0ZXMgdGhlIGxvZy1mb2xkIGNoYW5nZSBpbiBjb250cmFzdCB0byB0aGUgbG9nLWNvbmNlbnRyYXRpb24gZm9yIG91ciBjb3VudHMuIEkgdXNlIGBlZGdlUmAncyBNQSBwbG90IGZ1bmN0aW9uYWxpdHkgZm9yIGJvdGggbW9kZWwgZGVzaWducy4KCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy5jYXA9IkZpZ3VyZSA0OiBNQSBQbG90IG9mIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGFmdGVyIGNvcnJlY3Rpb24gYWNyb3NzIGNsaW5pY2FsIHN1YnR5cGVzLCBhZ2dyZWdhdGUgZGVzaWduIn0KZWRnZVI6Om1hUGxvdChsb2dBYnVuZGFuY2U9dG9wX2hpdHMkdGFibGUkbG9nQ1BNLCAKICAgICAgICAgICAgICBsb2dGQz10b3BfaGl0cyR0YWJsZSRsb2dGQywKICAgICAgICAgICAgICBkZS50YWdzPXdoaWNoKHRvcF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUpLAogICAgICAgICAgICAgIGxvd2Vzcz1UUlVFLAogICAgICAgICAgICAgIHhsYWI9ImxvZyhjb3VudHMgcGVyIG1pbGxpb24pIiwKICAgICAgICAgICAgICB5bGFiPSJsb2coZm9sZC1jaGFuZ2UpIiwKICAgICAgICAgICAgICBtYWluPSJGaWd1cmUgNDogTUEgUGxvdCBvZiBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IAogICAgICAgICAgICAgIGV4cHJlc3NlZCBnZW5lcyBhZnRlciBjb3JyZWN0aW9uIGFjcm9zcyAKICAgICAgICAgICAgICBjbGluaWNhbCBzdWJ0eXBlcywgYWdncmVnYXRlIGRlc2lnbiIpCmxlZ2VuZCgidG9wcmlnaHQiLCB0aXRsZT0iU2lnbmlmaWNhbmNlIiwKICAgICAgIGxlZ2VuZD1jKCJub3Qgc2lnbmlmaWNhbnQiLCAKICAgICAgICAgICAgICAgICJzaWduaWZpY2FudCBhZnRlciBjb3JyZWN0aW9uIiksIAogICAgICAgY29sPWMoImJsYWNrIiwgInJlZCIpLCBwY2g9MSwgY2V4PTAuOCkKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcuY2FwPSJGaWd1cmUgNTogTUEgUGxvdCBvZiBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhZnRlciBjb3JyZWN0aW9uIGFzc29jaWF0ZWQgd2l0aCBFUiBleHByZXNzaW9uIn0KZWRnZVI6Om1hUGxvdChsb2dBYnVuZGFuY2U9dG9wX2VycCR0YWJsZSRsb2dDUE0sIAogICAgICAgICAgICAgIGxvZ0ZDPXRvcF9lcnAkdGFibGUkbG9nRkMsCiAgICAgICAgICAgICAgZGUudGFncz13aGljaCh0b3BfZXJwJHRhYmxlJEZEUiA8IDAuMDUpLAogICAgICAgICAgICAgIGxvd2Vzcz1UUlVFLAogICAgICAgICAgICAgIHhsYWI9ImxvZyhjb3VudHMgcGVyIG1pbGxpb24pIiwKICAgICAgICAgICAgICB5bGFiPSJsb2coZm9sZC1jaGFuZ2UpIiwKICAgICAgICAgICAgICBtYWluPSJGaWd1cmUgNTogTUEgUGxvdCBvZiBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IAogICAgICAgICAgICAgIGV4cHJlc3NlZCBnZW5lcyBhZnRlciBjb3JyZWN0aW9uIAogICAgICAgICAgICAgIGFzc29jaWF0ZWQgd2l0aCBFUiBleHByZXNzaW9uIikKbGVnZW5kKCJ0b3ByaWdodCIsIHRpdGxlPSJTaWduaWZpY2FuY2UiLAogICAgICAgbGVnZW5kPWMoIm5vdCBzaWduaWZpY2FudCIsIAogICAgICAgICAgICAgICAgInNpZ25pZmljYW50IGFmdGVyIGNvcnJlY3Rpb24iKSwgCiAgICAgICBjb2w9YygiYmxhY2siLCAicmVkIiksIHBjaD0xLCBjZXg9MC44KQpgYGAKCiMjIyBWb2xjYW5vIFBsb3QKClRoZSB2b2xjYW5vIHBsb3QgcHJvdmlkZXMgYW5vdGhlciB2aXN1YWwgZm9yIHRoZSBzcHJlYWQgb2Ygb3VyIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhbmQgdGhlaXIgc2lnbmlmaWNhbmNlLCBib3RoIGJlZm9yZSBhbmQgYWZ0ZXIgY29ycmVjdGlvbi4KClRoZSBncmVlbiBwb2ludHMgYXJlIHRob3NlIHdpdGggc2lnbmlmaWNhbnQgcC12YWx1ZXMgYmVmb3JlIGNvcnJlY3Rpb24sIHdpdGggdGhlIHJlZCBwb2ludHMgYmVpbmcgc2lnbmlmaWNhbnQgZ2VuZXMgYWZ0ZXIgY29ycmVjdGlvbi4KCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy5jYXA9IkZpZ3VyZSA2OiBWb2xjYW5vIFBsb3Qgb2Ygc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgYWZ0ZXIgY29ycmVjdGlvbiBhY3Jvc3MgY2xpbmljYWwgc3VidHlwZXMsIGFnZ3JlZ2F0ZSBkZXNpZ24ifQpwbG90KHRvcF9oaXRzJHRhYmxlJGxvZ0ZDLCAtMTAqbG9nMTAodG9wX2hpdHMkdGFibGUkUFZhbHVlKSwKICAgICBtYWluPSJGaWd1cmUgNjogVm9sY2FubyBQbG90IG9mIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgCiAgICAgZXhwcmVzc2VkIGdlbmVzIGFmdGVyIGNvcnJlY3Rpb24gCiAgICAgYWNyb3NzIGNsaW5pY2FsIHN1YnR5cGVzLCBhZ2dyZWdhdGUgZGVzaWduIiwKICAgICB4bGFiPSJsb2coZm9sZCBjaGFuZ2UpIiwKICAgICB5bGFiPSItMTBebG9nKHAtdmFsdWUpIikKIyBoaWdobGlnaHQgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzCnBvaW50cyh0b3BfaGl0cyR0YWJsZSRsb2dGQ1t3aGljaCh0b3BfaGl0cyR0YWJsZSRQVmFsdWUgPCAwLjA1KV0sCiAgICAgICAtMTAqbG9nMTAodG9wX2hpdHMkdGFibGUkUFZhbHVlKVt3aGljaCh0b3BfaGl0cyR0YWJsZSRQVmFsdWUgPCAwLjA1KV0sCiAgICAgICBjb2w9ImdyZWVuIikKcG9pbnRzKHRvcF9oaXRzJHRhYmxlJGxvZ0ZDW3doaWNoKHRvcF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUpXSwKICAgICAgIC0xMCpsb2cxMCh0b3BfaGl0cyR0YWJsZSRQVmFsdWUpW3doaWNoKHRvcF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUpXSwKICAgICAgIGNvbD0icmVkIikKbGVnZW5kKCJ0b3BsZWZ0IiwgdGl0bGU9IlNpZ25pZmljYW5jZSIsCiAgICAgICBsZWdlbmQ9Yygibm90IHNpZ25pZmljYW50IiwgCiAgICAgICAgICAgICAgICAic2lnbmlmaWNhbnQgYmVmb3JlIGNvcnJlY3Rpb24iLCAKICAgICAgICAgICAgICAgICJzaWduaWZpY2FudCBhZnRlciBjb3JyZWN0aW9uIiksIAogICAgICAgY29sPWMoImJsYWNrIiwgImdyZWVuIiwgInJlZCIpLCBwY2g9MSwgY2V4PTAuOCkKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcuY2FwPSJGaWd1cmUgNzogVm9sY2FubyBQbG90IG9mIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGFmdGVyIGNvcnJlY3Rpb24gYXNzb2NpYXRlZCB3aXRoIEVSIGV4cHJlc3Npb24ifQpwbG90KHRvcF9lcnAkdGFibGUkbG9nRkMsIC0xMCpsb2cxMCh0b3BfZXJwJHRhYmxlJFBWYWx1ZSksCiAgICAgbWFpbj0iRmlndXJlIDc6IFZvbGNhbm8gUGxvdCBvZiBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IAogICAgIGV4cHJlc3NlZCBnZW5lcyBhZnRlciBjb3JyZWN0aW9uIAogICAgIGFzc29jaWF0ZWQgd2l0aCBFUiBleHByZXNzaW9uIiwKICAgICB4bGFiPSJsb2coZm9sZCBjaGFuZ2UpIiwKICAgICB5bGFiPSItMTBebG9nKHAtdmFsdWUpIikKIyBoaWdobGlnaHQgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzCnBvaW50cyh0b3BfZXJwJHRhYmxlJGxvZ0ZDW3doaWNoKHRvcF9lcnAkdGFibGUkUFZhbHVlIDwgMC4wNSldLAogICAgICAgLTEwKmxvZzEwKHRvcF9lcnAkdGFibGUkUFZhbHVlKVt3aGljaCh0b3BfZXJwJHRhYmxlJFBWYWx1ZSA8IDAuMDUpXSwKICAgICAgIGNvbD0iZ3JlZW4iKQpwb2ludHModG9wX2VycCR0YWJsZSRsb2dGQ1t3aGljaCh0b3BfZXJwJHRhYmxlJEZEUiA8IDAuMDUpXSwKICAgICAgIC0xMCpsb2cxMCh0b3BfZXJwJHRhYmxlJFBWYWx1ZSlbd2hpY2godG9wX2VycCR0YWJsZSRGRFIgPCAwLjA1KV0sCiAgICAgICBjb2w9InJlZCIpCmxlZ2VuZCgidG9wbGVmdCIsIHRpdGxlPSJTaWduaWZpY2FuY2UiLAogICAgICAgbGVnZW5kPWMoIm5vdCBzaWduaWZpY2FudCIsIAogICAgICAgICAgICAgICAgInNpZ25pZmljYW50IGJlZm9yZSBjb3JyZWN0aW9uIiwgCiAgICAgICAgICAgICAgICAic2lnbmlmaWNhbnQgYWZ0ZXIgY29ycmVjdGlvbiIpLCAKICAgICAgIGNvbD1jKCJibGFjayIsICJncmVlbiIsICJyZWQiKSwgcGNoPTEsIGNleD0wLjgpCmBgYAoKVGhpcyB2b2xjYW5vIHBsb3Qgb2YgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIHdpdGggcmVnYXJkcyB0byBgRVItYCBhbmQgYEVSK2AgaXMgdmVyeSBpbnRlcmVzdGluZyBnaXZlbiBpdHMgc3Ryb25nIHNrZXcgdG93YXJkcyB1cC1yZWd1bGF0aW9uLgoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLmNhcD0iRmlndXJlIDg6IFZvbGNhbm8gUGxvdCBvZiBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhZnRlciBjb3JyZWN0aW9uIGFzc29jaWF0ZWQgd2l0aCBIRVIyIGV4cHJlc3Npb24ifQpwbG90KHRvcF9oZXIycCR0YWJsZSRsb2dGQywgLTEwKmxvZzEwKHRvcF9oZXIycCR0YWJsZSRQVmFsdWUpLAogICAgIG1haW49IkZpZ3VyZSA4OiBWb2xjYW5vIFBsb3Qgb2Ygc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSAKICAgICBleHByZXNzZWQgZ2VuZXMgYWZ0ZXIgY29ycmVjdGlvbiAKICAgICBhc3NvY2lhdGVkIHdpdGggSEVSMiBleHByZXNzaW9uIiwKICAgICB4bGFiPSJsb2coZm9sZCBjaGFuZ2UpIiwKICAgICB5bGFiPSItMTBebG9nKHAtdmFsdWUpIikKIyBoaWdobGlnaHQgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzCnBvaW50cyh0b3BfaGVyMnAkdGFibGUkbG9nRkNbd2hpY2godG9wX2hlcjJwJHRhYmxlJFBWYWx1ZSA8IDAuMDUpXSwKICAgICAgIC0xMCpsb2cxMCh0b3BfaGVyMnAkdGFibGUkUFZhbHVlKVt3aGljaCh0b3BfaGVyMnAkdGFibGUkUFZhbHVlIDwgMC4wNSldLAogICAgICAgY29sPSJncmVlbiIpCnBvaW50cyh0b3BfaGVyMnAkdGFibGUkbG9nRkNbd2hpY2godG9wX2hlcjJwJHRhYmxlJEZEUiA8IDAuMDUpXSwKICAgICAgIC0xMCpsb2cxMCh0b3BfaGVyMnAkdGFibGUkUFZhbHVlKVt3aGljaCh0b3BfaGVyMnAkdGFibGUkRkRSIDwgMC4wNSldLAogICAgICAgY29sPSJyZWQiKQpsZWdlbmQoInRvcGxlZnQiLCB0aXRsZT0iU2lnbmlmaWNhbmNlIiwKICAgICAgIGxlZ2VuZD1jKCJub3Qgc2lnbmlmaWNhbnQiLCAKICAgICAgICAgICAgICAgICJzaWduaWZpY2FudCBiZWZvcmUgY29ycmVjdGlvbiIsIAogICAgICAgICAgICAgICAgInNpZ25pZmljYW50IGFmdGVyIGNvcnJlY3Rpb24iKSwgCiAgICAgICBjb2w9YygiYmxhY2siLCAiZ3JlZW4iLCAicmVkIiksIHBjaD0xLCBjZXg9MC44KQpgYGAKCkJvdGggdGhlIGFnZ3JlZ2F0ZSBtb2RlbCBkZXNpZ24sIGFuZCB0aGUgYEhFUjJgIGRlc2lnbiBhcmUgZmFpcmx5IGV2ZW5seSBkaXN0cmlidXRlZCBhcm91bmQgMC4KCiMjIFZpc3VhbGl6aW5nIHRvcCBoaXRzCgojIyMgSGVhdG1hcAoKQWdncmVnYXRpbmcgb3VyIHRvcCBoaXRzIGFjcm9zcyBjbGluaWNhbCBzdWJ0eXBlcyBpbnRvIGEgaGVhdG1hcCwgd2UgY2FuIHNlZSB0aGUgZXhwcmVzc2lvbiB2aXN1YWxseSBhcyBzaG93biwgYWxvbmcgd2l0aCBhIGhlYXRtYXAgYW5ub3RhdGlvbiBjb3JyZXNwb25kaW5nIHRvIGVhY2ggYmluYXJ5IHBhaXJpbmcgcmVwcmVzZW50ZWQgYnkgdGhlIHN1YnR5cGUgY2xhc3NpZmllci4KCmBgYHtyfQp0b3BzIDwtIHJvd25hbWVzKHFsZi5zdWJ0eXBlcyR0YWJsZSlbCiAgcWxmLnN1YnR5cGVzJHRhYmxlJFBWYWx1ZSA8IDAuMDUKXQp0b3BfaGl0c19tYXRyaXggPSB0KHNjYWxlKAogIHQobm9ybV9tYXRyaXhbd2hpY2gocm93bmFtZXMobm9ybV9tYXRyaXgpICVpbiUgdG9wcyksXSkKKSkKCiMgY29sb3VycwppZiAobWluKHRvcF9oaXRzX21hdHJpeCkgPT0gMCkgewogIGhlYXRtYXBfY29sID0gY29sb3JSYW1wMihjKDAsIG1heCh0b3BfaGl0c19tYXRyaXgpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYygid2hpdGUiLCAicmVkIikpCn0gZWxzZSB7CiAgaGVhdG1hcF9jb2wgPSBjb2xvclJhbXAyKGMobWluKHRvcF9oaXRzX21hdHJpeCksIDAsIG1heCh0b3BfaGl0c19tYXRyaXgpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiYmx1ZSIsICJ3aGl0ZSIsICJyZWQiKSkKfQoKIyBhbm5vdGF0aW9ucwpoZXIyX2NvbCA8LSBjKCJsaWdodGdyZWVuIiwgInJlZCIpCm5hbWVzKGhlcjJfY29sKSA8LSBjKCdUUlVFJywgJ0ZBTFNFJykKZXJfY29sIDwtIGMoImRhcmtncmVlbiIsICJwaW5rIikKbmFtZXMoZXJfY29sKSA8LSBjKCdUUlVFJywgJ0ZBTFNFJykKCnR5cGVzX2RmJGhlcjIgPC0gZmFjdG9yKHR5cGVzX2RmJGhlcjIsIGxldmVscyA9IGMoJ1RSVUUnLCdGQUxTRScpKQp0eXBlc19kZiRlciA8LSBmYWN0b3IodHlwZXNfZGYkZXIsIGxldmVscyA9IGMoJ1RSVUUnLCdGQUxTRScpKQoKaGVhdG1hcF9hbm5vdGF0aW9uIDwtIENvbXBsZXhIZWF0bWFwOjpIZWF0bWFwQW5ub3RhdGlvbigKICBkZiA9IGRhdGEuZnJhbWUoaGVyMiA9IHR5cGVzX2RmJGhlcjIsCiAgICAgICAgICAgICAgICAgIGVyID0gdHlwZXNfZGYkZXIpLAogIGNvbCA9IGxpc3QoaGVyMiA9IGhlcjJfY29sLCBlciA9IGVyX2NvbCksCiAgc2hvd19sZWdlbmQ9VFJVRQopCgpoZWF0bWFwIDwtIENvbXBsZXhIZWF0bWFwOjpIZWF0bWFwKGFzLm1hdHJpeCh0b3BfaGl0c19tYXRyaXgpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfcm93cz1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1ucz1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfcm93X2RlbmQ9VFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd19jb2x1bW5fZGVuZD1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbD1oZWF0bWFwX2NvbCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd19jb2x1bW5fbmFtZXM9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd19yb3dfbmFtZXM9RkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfaGVhdG1hcF9sZWdlbmQ9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lPSJjb2xvdXIgc2NhbGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvcF9hbm5vdGF0aW9uPWhlYXRtYXBfYW5ub3RhdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW5fdGl0bGU9IkZpZ3VyZSA5OiBIZWF0bWFwIG9mIHRvcCBoaXRzIGFjcm9zcyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGluaWNhbCBzdWJ0eXBlcywgYWdncmVnYXRlIGRlc2lnbiIpCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9OCwgZmlnLmNhcD0iRmlndXJlIDk6IEhlYXQgbWFwIG9mIHRvcCBoaXRzIGFjcm9zcyBjbGluaWNhbCBzdWJ0eXBlcywgYWdncmVnYXRlIGRlc2lnbiB3aXRoIGJpbmFyeSBsYWJlbGxpbmcifQpoZWF0bWFwCmBgYAoKU3BlY2lmaWNhbGx5IGZvciBgRVJgIG92ZXJleHByZXNzaW9uIG9yIGxhY2sgdGhlcmVvZiwgSSBhZGRlZCBhbiBhZGRpdGlvbmFsIGhlYXRtYXAuCgpgYGB7cn0KdG9wc19lciA8LSByb3duYW1lcyhxbGYuZXJwJHRhYmxlKVsKICBxbGYuZXJwJHRhYmxlJFBWYWx1ZSA8IDAuMDUKXQp0b3BzX2VyX21hdHJpeCA9IHQoc2NhbGUoCiAgdChub3JtX21hdHJpeFt3aGljaChyb3duYW1lcyhub3JtX21hdHJpeCkgJWluJSB0b3BzX2VyKSxdKQopKQoKIyBjb2xvdXJzCmlmIChtaW4odG9wc19lcl9tYXRyaXgpID09IDApIHsKICBoZWF0bWFwX2NvbCA9IGNvbG9yUmFtcDIoYygwLCBtYXgodG9wc19lcl9tYXRyaXgpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYygid2hpdGUiLCAicmVkIikpCn0gZWxzZSB7CiAgaGVhdG1hcF9jb2wgPSBjb2xvclJhbXAyKGMobWluKHRvcHNfZXJfbWF0cml4KSwgMCwgbWF4KHRvcHNfZXJfbWF0cml4KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpCn0KCmhlYXRtYXBfZXIgPC0gQ29tcGxleEhlYXRtYXA6OkhlYXRtYXAoYXMubWF0cml4KHRvcHNfZXJfbWF0cml4KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3M9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHVzdGVyX2NvbHVtbnM9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93X3Jvd19kZW5kPVRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfY29sdW1uX2RlbmQ9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2w9aGVhdG1hcF9jb2wsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfY29sdW1uX25hbWVzPUZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfcm93X25hbWVzPUZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93X2hlYXRtYXBfbGVnZW5kPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT0iY29sb3VyIHNjYWxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3BfYW5ub3RhdGlvbj1oZWF0bWFwX2Fubm90YXRpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uX3RpdGxlPSJGaWd1cmUgMTA6IEhlYXRtYXAgb2YgdG9wIGhpdHMgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzb2NpYXRlZCB3aXRoIEVSIG92ZXJleHByZXNzaW9uIikKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD04LCBmaWcuY2FwPSJGaWd1cmUgMTA6IEhlYXRtYXAgb2YgdG9wIGhpdHMgYXNzb2NpYXRlZCB3aXRoIEVSIG92ZXJleHByZXNzaW9uIn0KaGVhdG1hcF9lcgpgYGAKCiMjIyBEbyBjb25kaXRpb25zIGNsdXN0ZXIgdG9nZXRoZXI/IEV4cGxhaW4uCgpJbiBmaWd1cmUgOSwgdGhlcmUgaXMgdmVyeSB2aXNpYmx5IGEgY2x1c3RlciBkZW1vbnN0cmF0ZWQgYmV0d2VlbiBoZWF0IGludGVuc2l0eSBhbmQgYEVSYCBvdmVyZXhwcmVzc2lvbiBvciBsYWNrIHRoZXJlb2Ygd2l0aCB0aGUgZ2VuZXMgcHJpbWFyaWx5IGluIHRoZSB0b3AgaGFsZiBiZWluZyBnZW5lcmFsbHkgaGlnaGx5IGV4cHJlc3NlZCBpbiBsYWNrIG9mIGBFUmAsIGFuZCBsb3dseSBleHByZXNzZWQgaW4gb3ZlcmV4cHJlc3Npb24gb2YgYEVSYC4gU2ltaWxhcmx5LCB0aGUgbG93ZXIgaGFsZiBvZiBnZW5lcyBwcmltYXJpbHkgZm9sbG93IHRoZSBvcHBvc2l0ZSB0cmVuZDsgbG93ZXIgZXhwcmVzc2lvbiBvbiBgRVItYCBhbmQgaGlnaGVyIGV4cHJlc3Npb24gb24gYEVSK2AuCgpJbiBmaWd1cmUgMTAsIGl0IGlzIG1vcmUgZGlmZmljdWx0IHRvIHNlZSB0aGUgY2x1c3RlciBwYXR0ZXJucy4gU2FtcGxlIDEgaGFzIHZlcnkgaW50ZW5zZSBSTkEgZXhwcmVzc2lvbnMgaW4gdGhlIHRvcCBoYWxmIG9mIGdlbmVzLCBidXQgaXRzIG1hdGNoaW5nIGBIRVIyKy9FUi1gIHN1YnR5cGUgbGFja3MgdGhpcyBhdCBhbGwuIFRoaXMgaW1wbGllcyB0aGUgYXNzb2NpYXRpb24gZ29lcyBpbiBhIGJyb2FkZXIgc2NhbGUgdGhhbiBsYWNrIG9mIGBFUmAgZm9yIHRoZXNlIGdlbmVzLiBEZXNwaXRlIDExIGdlbmVzIGJlaW5nIGFzc29jaWF0ZWQgd2l0aCBvdmVyZXhwcmVzc2lvbiBvZiBgRVJgLCBpdCBkb2VzIG5vdCBhcHBlYXIgdG8gc2hvdyBhIHZpc2libGUgY2x1c3RlciBvbiB0aGUgaGVhdG1hcCBsaWtlIHRoZSBhZ2dyZWdhdGUgZGVzaWduIGluIGZpZ3VyZSA5IGRvZXMgcHJldHR5IHdlbGwuCgojIFRocmVzaG9sZGVkIE92ZXItUmVwcmVzZW50YXRpb24gQW5hbHlzaXMKCldpdGggb3VyIHNpZ25pZmljYW50bHkgdXAtcmVndWxhdGVkLCBhbmQgZG93bi1yZWd1bGF0ZWQgZ2VuZS1zZXRzLCB3ZSB3aWxsIHJ1biBhIHRocmVzaG9sZGVkIGdlbmUtc2V0IGVucmljaG1lbnQgYW5hbHlzaXMuCgpXZSBoYXZlIGByIGxlbmd0aCh3aGljaChxbGYuc3VidHlwZXMkdGFibGUkUFZhbHVlIDwgMC4wNSAmIHFsZi5zdWJ0eXBlcyR0YWJsZSRsb2dGQyA+IDApKWAgdXAtcmVndWxhdGVkIGdlbmVzLCBhbmQgYHIgbGVuZ3RoKHdoaWNoKHFsZi5zdWJ0eXBlcyR0YWJsZSRQVmFsdWUgPCAwLjA1ICYgcWxmLnN1YnR5cGVzJHRhYmxlJGxvZ0ZDIDwgMCkpYCBkb3duLXJlZ3VsYXRlZCBnZW5lcyBmb3Igb3VyIGFnZ3JlZ2F0ZSBtb2RlbCBkZXNpZ24gYWNyb3NzIGFsbCBjbGluaWNhbCBzdWJ0eXBlcy4KCmBgYHtyfQojIGNyZWF0ZSBub24tdGhyZXNob2xkZWQgZ2VuZSBzZXRzCm50X2dlbmVzZXQgPC0gcWxmLnN1YnR5cGVzJHRhYmxlCm50X2dlbmVzZXRbLCJyYW5rIl0gPC0gLWxvZzEwKG50X2dlbmVzZXQkUFZhbHVlKSAqIHNpZ24obnRfZ2VuZXNldCRsb2dGQykKbnRfZ2VuZXNldCA8LSBudF9nZW5lc2V0W29yZGVyKG50X2dlbmVzZXQkcmFuayksXQpgYGAKCmBgYHtyfQojIGNyZWF0ZSB0aHJlc2hvbGRlZCB1cCBhbmQgZG93biBnZW5lIHNldHMKdXByZWcgPC0gcm93bmFtZXMobnRfZ2VuZXNldClbd2hpY2gobnRfZ2VuZXNldCRQVmFsdWUgPCAwLjA1CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICYgbnRfZ2VuZXNldCRsb2dGQyA+IDApXQpkb3ducmVnIDwtIHJvd25hbWVzKG50X2dlbmVzZXQpW3doaWNoKG50X2dlbmVzZXQkUFZhbHVlIDwgMC4wNQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICYgbnRfZ2VuZXNldCRsb2dGQyA8IDApXQpgYGAKCmBgYHtyfQojIGZ1bmN0aW9uIGZvciByZXRyaWV2aW5nIGc6R09TdCBmcm9tIGc6UHJvZmlsZXIKZ29zdF9yZXMgPC0gZnVuY3Rpb24ocXVlcnkpIHsKICByZXMgPC0gZ29zdChxdWVyeSA9IHF1ZXJ5LAogICAgICAgICAgICAgICAgICAgICAgc2lnbmlmaWNhbnQ9RkFMU0UsICMgc2V0IG91ciBvd24gdGhyZXNob2xkCiAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkX3F1ZXJ5ID0gVFJVRSwgIyBvcmRlcmVkIGJ5IHJhbmsKICAgICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVfaWVhPVRSVUUsICMgZXhjbHVkZSBlbGVjdHJvbmljIEdPIGFubm90YXRpb25zCiAgICAgICAgICAgICAgICAgICAgICBjb3JyZWN0aW9uX21ldGhvZCA9ICJmZHIiLCAjIEJICiAgICAgICAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICJoc2FwaWVucyIsCiAgICAgICAgICAgICAgICAgICAgICBzb3VyY2UgPSBjKCJSRUFDIiwiV1AiLCJHTzpCUCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR086Q0MiLCAiR086TUYiLCAiS0VHRyIpKQogIHJldHVybihyZXMpCn0KYGBgCgpJIHF1ZXJ5IG91ciBnZW5lc2V0cyB1c2luZyBgZzpQcm9maWxlcmAncyBgZzpHT1N0YC4KCmBgYHtyfQojIHVwIGFuZCBkb3duIHJlZ3VsYXRlZCB0aHJlc2hvbGRlZCBnZW5lcwphbGwgPC0gZ29zdF9yZXModW5pcXVlKGModXByZWcsIGRvd25yZWcpKSkKIyBvbmx5IHVwIHJlZ3VsYXRlZCB0aHJlc2hvbGRlZCBnZW5lcwp1cCA8LSBnb3N0X3Jlcyh1cHJlZykKIyBvbmx5IGRvd24gcmVndWxhdGVkIHRocmVzaG9sZGVkIGdlbmVzCmRvd24gPC0gZ29zdF9yZXMoZG93bnJlZykKYGBgCgpgYGB7ciwgZWNobz1GQUxTRX0KYWxsJHJlc3VsdFsxOjUsYygzLCA5LCAxMSldICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSA3OiBIZWFkIG9mIHRocmVzaG9sZGVkIHVwIGFuZCBkb3duIHJlZ3VsYXRlZCBnZW5lcyBmcm9tIGc6R09TdCIpICU+JQogIGthYmxlX3N0eWxpbmcKYGBgCgpgYGB7ciwgZWNobz1GQUxTRX0KdXAkcmVzdWx0WzE6NSxjKDMsIDksIDExKV0gJT4lCiAga25pdHI6OmthYmxlKGNhcHRpb249IlRhYmxlIDg6IEhlYWQgb2YgdGhyZXNob2xkZWQgdXAtcmVndWxhdGVkIGdlbmVzIGZyb20gZzpHT1N0IikgJT4lCiAga2FibGVfc3R5bGluZwpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFfQpkb3duJHJlc3VsdFsxOjUsYygzLCA5LCAxMSldICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSA5OiBIZWFkIG9mIHRocmVzaG9sZGVkIGRvd24tcmVndWxhdGVkIGdlbmVzIGZyb20gZzpHT1N0IikgJT4lCiAga2FibGVfc3R5bGluZwpgYGAKCiMjIFdoaWNoIG1ldGhvZCBkaWQgeW91IGNob29zZSBhbmQgd2h5PwoKSSBjaG9zZSB0byB1c2UgYGc6UHJvZmlsZXJgIHdpdGggUiBzaW5jZSBpdCB3YXMgd2VsbCBkb2N1bWVudGVkIGJ5IFJ1dGggSXNzZXJsaW4gW0ByaXNzZXJsaW5dIGFuZCBJIGhhZCBmYW1pbGlhcml0eSB3aXRoIGl0IHRocm91Z2ggbXkgam91cm5hbCBlbnRyeS4gCgpgZzpQcm9maWxlcmAgcHJvdmlkZXMgYW4gYE9SQWAgKG92ZXItcmVwcmVzZW50YXRpb24gYW5hbHlzaXMpIG1ldGhvZCwgYW5kIHRoaXMgaXMgZXhhY3RseSB0aGUgbWV0aG9kIEkgd2FudCB0byBwZXJmb3JtIG9uIG15IHRocmVzaG9sZGVkIGRhdGEuCgojIyBXaGljaCBhbm5vdGF0aW9uIGRhdGEgZGlkIHlvdSB1c2UgYW5kIHdoeT8gCgpJIGNob3NlIHRoZSBmb2xsb3dpbmcgYW5ub3RhdGlvbiBzb3VyY2VzIHRvIGdldCB0aGUgbW9zdCBjb21wcmVoZW5zaXZlIHJlc3VsdHMgZm9yIG91ciBmdW5jdGlvbmFsIGVucmljaG1lbnQgYW5hbHlzaXMgcmVsYXRpdmUgdG8gYmlvbG9naWNhbCBwcm9jZXNzZXMgYW5kIGdlbmUgb250b2xvZ3k6CgoqIGBHTzpCUGAgOiBgR2VuZSBPbnRvbG9neTogQmlvbG9naWNhbCBQcm9jZXNzZXNgCiogYFJFQUNgIDogYFJlYWN0b21lYAoqIGBXUGAgOiBgV2lraVBhdGh3YXlzYAoqIGBHTzpDQ2AgOiBgR2VuZSBPbnRvbG9neTogQ2VsbHVsYXIgQ29tcG9uZW50c2AKKiBgR086TUZgIDogYEdlbmUgT250b2xvZ3k6IE1vbGVjdWxhciBGdW5jdGlvbmAKKiBgS0VHR2AgOiBgS3lvdG8gRW5jeWNsb3BlZGlhIG9mIEdlbmVzIGFuZCBHZW5vbWVzYAoKYEdPOkJQYCwgYFJFQUNgLCBhbmQgYFdQYCB3ZXJlIHJlY29tbWVuZGVkIGJ5IFByb2Zlc3NvciBJc3NlcmxpbiwgaG93ZXZlciBJIHJhbiB0aGUgT1JBIHVzaW5nIHRoZXNlIGFuZCBmb3VuZCBub3RoaW5nIGp1bXBlZCBvdXQgZnJvbSB0aGUgcmVzdWx0aW5nIHBsb3RzLiBBcyBzdWNoLCBJIHJldmlzaXRlZCB0byBleHBhbmQgdGhlIHNjb3BlIG9mIGFubm90YXRpb24gc291cmNlcyBpbiBob3BlcyBmb3IgYSBtb3JlIGluZm9ybWF0aXZlIHJlc3VsdC4KCiMjIyBXaGF0IHZlcnNpb24gb2YgdGhlIGFubm90YXRpb24gYXJlIHlvdSB1c2luZz8KCmBgYHtyLCBlY2hvPUZBTFNFfQp2ZXJzaW9uX2luZm8gPC0gZ3Byb2ZpbGVyMjo6Z2V0X3ZlcnNpb25faW5mbyhvcmdhbmlzbSA9ICJoc2FwaWVucyIpCmdvYnAgPC0gdmVyc2lvbl9pbmZvJHNvdXJjZXMkYEdPOkJQYApnb2NjIDwtIHZlcnNpb25faW5mbyRzb3VyY2VzJGBHTzpDQ2AKZ29tZiA8LSB2ZXJzaW9uX2luZm8kc291cmNlcyRgR086TUZgCmBgYAoKRm9yIGBnOlByb2ZpbGVyYCB2ZXJzaW9uIGluZm9ybWF0aW9uLCBJIHVzZWQ6CgoqIGBnOlByb2ZpbGVyYCB2ZXJzaW9uOiBfX2ByIHZlcnNpb25faW5mbyRncHJvZmlsZXJfdmVyc2lvbmBfXwoqIGBiaW9tYVJ0YCB2ZXJzaW9uOiBfX2ByIHZlcnNpb25faW5mbyRiaW9tYXJ0X3ZlcnNpb25gX18KCkZvciB0aGUgYW5ub3RhdGlvbiBzb3VyY2VzIHNlbGVjdGVkIGluIG15IHF1ZXJ5LCBJIHVzZWQ6CgoqIGBHTzpCUGAgdmVyc2lvbiBfX2ByIGdvYnAkdmVyc2lvbmBfXyAKKiBgUkVBQ2AgdmVyc2lvbiBfX2ByIHZlcnNpb25faW5mbyRzb3VyY2VzJFJFQUMkdmVyc2lvbmBfXwoqIGBXUGAgdmVyc2lvbiBfX2ByIHZlcnNpb25faW5mbyRzb3VyY2VzJFdQJHZlcnNpb25gX18KKiBgR086Q0NgIHZlcnNpb24gX19gciBnb2NjJHZlcnNpb25gX18gCiogYEdPOk1GYCB2ZXJzaW9uIF9fYHIgZ29tZiR2ZXJzaW9uYF9fIAoqIGBLRUdHYCB2ZXJzaW9uIF9fYHIgdmVyc2lvbl9pbmZvJHNvdXJjZXMkS0VHRyR2ZXJzaW9uYF9fCgojIyBIb3cgbWFueSBnZW5lLXNldHMgd2VyZSByZXR1cm5lZCB3aXRoIHdoYXQgdGhyZXNob2xkcz8KCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KdGhyZXNob2xkX3JlcyA8LSBmdW5jdGlvbihyZXN1bHQsIG1pbiwgbWF4LCBpbnRlcnNlY3Rpb24pIHsKICByZXQgPC0gc3Vic2V0KHJlc3VsdCwgdGVybV9zaXplID49IG1pbiAmCiAgICAgICAgICAgICAgICB0ZXJtX3NpemUgPD0gbWF4ICYKICAgICAgICAgICAgICAgIGludGVyc2VjdGlvbl9zaXplID49IGludGVyc2VjdGlvbiwKICAgICAgICAgICAgICAgIHNlbGVjdCA9IGModGVybV9pZCwgdGVybV9uYW1lLCBwX3ZhbHVlLCBzaWduaWZpY2FudCkpCiAgcmV0dXJuKHJldCkKfQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFfQp0aHJlc2hvbGRfZGYgPC0gZGF0YS5mcmFtZSgKICBjKGRpbSh0aHJlc2hvbGRfcmVzKGFsbCRyZXN1bHQsIDMsIDEwMCwgNSkpWzFdLAogICAgZGltKHRocmVzaG9sZF9yZXModXAkcmVzdWx0LCAzLCAxMDAsIDUpKVsxXSwKICAgIGRpbSh0aHJlc2hvbGRfcmVzKGRvd24kcmVzdWx0LCAzLCAxMDAsIDUpKVsxXSksCiAgYyhkaW0odGhyZXNob2xkX3JlcyhhbGwkcmVzdWx0LCAzLCAyNTAsIDUpKVsxXSwKICAgIGRpbSh0aHJlc2hvbGRfcmVzKHVwJHJlc3VsdCwgMywgMjUwLCA1KSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyhkb3duJHJlc3VsdCwgMywgMjUwLCA1KSlbMV0pLAogIGMoZGltKHRocmVzaG9sZF9yZXMoYWxsJHJlc3VsdCwgMywgMTAwMCwgNSkpWzFdLAogICAgZGltKHRocmVzaG9sZF9yZXModXAkcmVzdWx0LCAzLCAxMDAwLCA1KSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyhkb3duJHJlc3VsdCwgMywgMTAwMCwgNSkpWzFdKSwKICBjKGRpbSh0aHJlc2hvbGRfcmVzKGFsbCRyZXN1bHQsIDMsIDEwMDAwLCA1KSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyh1cCRyZXN1bHQsIDMsIDEwMDAwLCA1KSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyhkb3duJHJlc3VsdCwgMywgMTAwMDAsIDUpKVsxXSksCiAgcm93Lm5hbWVzPWMoIlVwICYgRG93biIsICJVcCIsICJEb3duIikpCgp0aHJlc2hvbGRfZGYgJT4lCiAga25pdHI6OmthYmxlKGNhcHRpb249IlRhYmxlIDEwOiBHZW5lLXNldCBzaXplcyBmb3IgZGlmZmVyZW50IG1heGltdW0gdGhyZXNob2xkcyB3aXRoIG1pbmltdW0gaW50ZXJzZWN0aW9uIG9mIDUiLAogICAgICAgICAgICAgICBjb2wubmFtZXM9YygiTWF4IDEwMCIsICJNYXggMjUwIiwgIk1heCAxMDAwIiwgIk1heCAxMDAwMDAiKSkgJT4lCiAga2FibGVfc3R5bGluZygpCmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CnRocmVzaG9sZF9kZiA8LSBkYXRhLmZyYW1lKAogIGMoZGltKHRocmVzaG9sZF9yZXMoYWxsJHJlc3VsdCwgMywgMTAwLCAxMCkpWzFdLAogICAgZGltKHRocmVzaG9sZF9yZXModXAkcmVzdWx0LCAzLCAxMDAsIDEwKSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyhkb3duJHJlc3VsdCwgMywgMTAwLCAxMCkpWzFdKSwKICBjKGRpbSh0aHJlc2hvbGRfcmVzKGFsbCRyZXN1bHQsIDMsIDI1MCwgMTApKVsxXSwKICAgIGRpbSh0aHJlc2hvbGRfcmVzKHVwJHJlc3VsdCwgMywgMjUwLCAxMCkpWzFdLAogICAgZGltKHRocmVzaG9sZF9yZXMoZG93biRyZXN1bHQsIDMsIDI1MCwgMTApKVsxXSksCiAgYyhkaW0odGhyZXNob2xkX3JlcyhhbGwkcmVzdWx0LCAzLCAxMDAwLCAxMCkpWzFdLAogICAgZGltKHRocmVzaG9sZF9yZXModXAkcmVzdWx0LCAzLCAxMDAwLCAxMCkpWzFdLAogICAgZGltKHRocmVzaG9sZF9yZXMoZG93biRyZXN1bHQsIDMsIDEwMDAsIDEwKSlbMV0pLAogIGMoZGltKHRocmVzaG9sZF9yZXMoYWxsJHJlc3VsdCwgMywgMTAwMDAsIDEwKSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyh1cCRyZXN1bHQsIDMsIDEwMDAwLCAxMCkpWzFdLAogICAgZGltKHRocmVzaG9sZF9yZXMoZG93biRyZXN1bHQsIDMsIDEwMDAwLCAxMCkpWzFdKSwKICByb3cubmFtZXM9YygiVXAgJiBEb3duIiwgIlVwIiwgIkRvd24iKSkKCnRocmVzaG9sZF9kZiAlPiUKICBrbml0cjo6a2FibGUoY2FwdGlvbj0iVGFibGUgMTE6IEdlbmUtc2V0IHNpemVzIGZvciBkaWZmZXJlbnQgbWF4aW11bSB0aHJlc2hvbGRzIHdpdGggbWluaW11bSBpbnRlcnNlY3Rpb24gb2YgMTAiLAogICAgICAgICAgICAgICBjb2wubmFtZXM9YygiTWF4IDEwMCIsICJNYXggMjUwIiwgIk1heCAxMDAwIiwgIk1heCAxMDAwMDAiKSkgJT4lCiAga2FibGVfc3R5bGluZygpCmBgYAoKQWZ0ZXIgdGhyZXNob2xkaW5nIHdpdGggbWF4aW11bSB2YWx1ZSBvZiAxMDAgYW5kIG1pbmltdW0gaW50ZXJzZWN0aW9uIG9mIDEwLCB3ZSBjYW4gc2VlIHRoZSB0ZXJtcyByZW1haW4gc2ltaWxhci4KCmBgYHtyLCBlY2hvPUZBTFNFfQp0aHJlc2hvbGRfcmVzKGFsbCRyZXN1bHQsIDMsIDEwMCwgMTApWzE6NSxdICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSAxMjogSGVhZCBvZiB0aHJlc2hvbGRlZCBbMywgMTAwXSB1cCBhbmQgZG93bi1yZWd1bGF0ZWQgZ2VuZXMgZnJvbSBPUkEgd2l0aCBpbnRlcnNlY3Rpb24gMTAiKSAlPiUKICBrYWJsZV9zdHlsaW5nCmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CnRocmVzaG9sZF9yZXModXAkcmVzdWx0LCAzLCAxMDAsIDEwKVsxOjUsXSAlPiUKICBrbml0cjo6a2FibGUoY2FwdGlvbj0iVGFibGUgMTM6IEhlYWQgb2YgdGhyZXNob2xkZWQgWzMsIDEwMF0gdXAtcmVndWxhdGVkIGdlbmVzIGZyb20gT1JBIHdpdGggaW50ZXJzZWN0aW9uIDEwIikgJT4lCiAga2FibGVfc3R5bGluZwpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFfQp0aHJlc2hvbGRfcmVzKGRvd24kcmVzdWx0LCAzLCAxMDAsIDEwKVsxOjUsXSAlPiUKICBrbml0cjo6a2FibGUoY2FwdGlvbj0iVGFibGUgMTQ6IEhlYWQgb2YgdGhyZXNob2xkZWQgWzMsIDEwMF0gZG93bi1yZWd1bGF0ZWQgZ2VuZXMgZnJvbSBPUkEgd2l0aCBpbnRlcnNlY3Rpb24gMTAiKSAlPiUKICBrYWJsZV9zdHlsaW5nCmBgYAoKQXMgc3VjaCwgd2UgZmluZCB0aGF0IHVwLXJlZ3VsYXRlZCBnZW5lcyBoYXZlIHNvbWUgc2lnbmlmaWNhbnQgZ2VuZS1zZXRzIGFmdGVyIHRocmVzaG9sZGluZywgd2hlcmVhcyBvdXIgZG93bi1yZWd1bGF0ZWQgZ2VuZXMgZmFpbCB0byBtYWludGFpbiBzaWduaWZpY2FuY2UuCgpPdXIgY29tYmluYXRpb24gdGFibGUgc2hvd3MgdXMgc3Ryb25nIG92ZXJsYXAgd2l0aCB0aGUgdXAtcmVndWxhdGVkIGdlbmVzLCBmdXJ0aGVyIHN1cHBvcnRpbmcgdGhlIHNpZ25pZmljYW5jZSBvZiBvdXIgdXAtcmVndWxhdGlvbiBza2V3ZWQgcmVzdWx0cy4KCiMjIENvbXBhcmluZyB1cC1yZWd1bGF0ZWQgYW5kIGRvd24tcmVndWxhdGVkIHNlcGFyYXRlIHZzLiB0b2dldGhlcgoKVGhlIGZvbGxvd2luZyBmaWd1cmVzIGRlbW9uc3RyYXRlIHRoZSBvdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzIHBsb3RzIGZvciBib3RoIHVwICYgZG93biByZWd1bGF0ZWQsIHVwLXJlZ3VsYXRlZCwgYW5kIGRvd24tcmVndWxhdGVkIGdlbmVzIHJlc3BlY3RpdmVseSB3aXRoIG9ubHkgYSBjb3VwbGUgb2YgcG9pbnRzIG1hbnVhbGx5IGhpZ2hsaWdodGVkLgoKIVtGaWd1cmUgMTE6IE92ZXItcmVwcmVzZW50YXRpb24gYW5hbHlzaXMgb2YgVXAgYW5kIERvd24gcmVndWxhdGVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzXSgvaG9tZS9yc3R1ZGlvL3Byb2plY3RzL2ZpZ3VyZXMvYWxsX29yYS5wbmcpCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD03LCBmaWcuY2FwPSJGaWd1cmUgMTE6IE92ZXItcmVwcmVzZW50YXRpb24gYW5hbHlzaXMgb2YgVXAgYW5kIERvd24tcmVndWxhdGVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIn0KIyBhbGxfcGxvdCA8LSBnb3N0cGxvdChhbGwsIGNhcHBlZCA9IEZBTFNFLCBpbnRlcmFjdGl2ZSA9IEZBTFNFKQojIGFsbF9wdWIgPC0gcHVibGlzaF9nb3N0cGxvdChhbGxfcGxvdCwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGlnaGxpZ2h0X3Rlcm1zID0gYygiR086MDA0NTI5NiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdPOjAwMzE5ODEiLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR086MDE0MDUxMyIpICkgKwojICAgZ2d0aXRsZSgiRmlndXJlIDExOiBPdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzIG9mIFVwIGFuZCBEb3duLXJlZ3VsYXRlZCBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyIpCmBgYAo8YnIvPgoKIVtGaWd1cmUgMTI6IE92ZXItcmVwcmVzZW50YXRpb24gYW5hbHlzaXMgb2YgVXAtcmVndWxhdGVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzXSgvaG9tZS9yc3R1ZGlvL3Byb2plY3RzL2ZpZ3VyZXMvdXBfb3JhLnBuZykKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTcsIGZpZy5jYXA9IkZpZ3VyZSAxMjogT3Zlci1yZXByZXNlbnRhdGlvbiBhbmFseXNpcyBvZiBVcC1yZWd1bGF0ZWQgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMifQojIHVwX3Bsb3QgPC0gZ29zdHBsb3QodXAsIGNhcHBlZCA9IEZBTFNFLCBpbnRlcmFjdGl2ZSA9IEZBTFNFKQojIHVwX3B1YiA8LSBwdWJsaXNoX2dvc3RwbG90KHVwX3Bsb3QsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpZ2hsaWdodF90ZXJtcyA9IGMoIkdPOjAwNDUyOTYiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdPOjAwMzE5ODEiLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHTzowMTQwNTEzIikpICsKIyAgIGdndGl0bGUoIkZpZ3VyZSAxMjogT3Zlci1yZXByZXNlbnRhdGlvbiBhbmFseXNpcyBvZiBVcC1yZWd1bGF0ZWQgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMiKQpgYGAKPGJyLz4KCiFbRmlndXJlIDEzOiBPdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzIG9mIERvd24tcmVndWxhdGVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzXSgvaG9tZS9yc3R1ZGlvL3Byb2plY3RzL2ZpZ3VyZXMvZG93bl9vcmEucG5nKQoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NywgZmlnLmNhcD0iRmlndXJlIDEzOiBPdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzIG9mIERvd24tcmVndWxhdGVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIn0KIyBkb3duX3Bsb3QgPC0gZ29zdHBsb3QoZG93biwgY2FwcGVkID0gRkFMU0UsIGludGVyYWN0aXZlID0gRkFMU0UpCiMgZG93bl9wdWIgPC0gcHVibGlzaF9nb3N0cGxvdChkb3duX3Bsb3QsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGlnaGxpZ2h0X3Rlcm1zID0gYygiR086MDA0NTI5NiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHTzowMDMxOTgxIiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHTzowMTQwNTEzIikpICsKIyAgIGdndGl0bGUoIkZpZ3VyZSAxMjogT3Zlci1yZXByZXNlbnRhdGlvbiBhbmFseXNpcyBvZiBEb3duLXJlZ3VsYXRlZCBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyIpCmBgYAoKIyMjIEhvdyBkbyB0aGVzZSByZXN1bHRzIGNvbXBhcmU/CgpTaW5jZSB0aGUgdXAtcmVndWxhdGVkIGdlbmUgcmVzdWx0cyB0ZW5kIHRvIGV4Y2VlZCB0aGUgZG93bi1yZWd1bGF0ZWQgZ2VuZSByZXN1bHRzIGluIHRlcm1zIG9mIHRlcm0gc2lnbmlmaWNhbmNlLCB0aGUgY29tYmluZWQgcGxvdCBhcHBlYXJzIHRvIG1vcmUgY2xvc2VseSByZXNlbWJsZSB0aGUgdXAtcmVndWxhdGVkIHBsb3QuCgpJbiBvdXIgY2FzZSwgT1JBIG9mIHVwIGFuZCBkb3duLXJlZ3VsYXRlZCBnZW5lcyBpbiBjb21iaW5hdGlvbiBkaWQgbm90IGhhdmUgYSBsYXJnZSBlZmZlY3Qgb24gdGhlIHJlc3VsdHMsIGJ1dCB0aGlzIGlzIGJlY2F1c2UgdGhlIHVwLXJlZ3VsYXRlZCBnZW5lcyBvdmVyc2hhZG93IHRoZSBkb3duLXJlZ3VsYXRlZC4gSWYgdGhpcyB3ZXJlIGEgZGlmZmVyZW50IGNhc2UsIHdlIGNvdWxkIHNlZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB1cC0gYW5kIGRvd24tcmVndWxhdGVkIHBsb3RzIG92ZXJzaGFkb3dlZCBhbmQgbWVsdGVkIGJ5IHRoZSBjb21iaW5hdGlvbiBwbG90LiBBcyBzdWNoLCBpdCBpcyBpbXBvcnRhbnQgdG8gbG9vayBhdCBib3RoIHVwLSBhbmQgZG93bi1yZWd1bGF0ZWQgc2VwYXJhdGVseS4KCkFsdGhvdWdoLCBpbiB0ZXJtcyBvZiBvdXIgcmVzdWx0cyBvZiB0aGlzIGFuYWx5c2lzLCBhbHRob3VnaCBzb21lIHRlcm1zIGFyZSBzaWduaWZpY2FudCBhY2NvcmRpbmcgdG8gb3VyIGFyYml0cmFyeSB0aHJlc2hvbGQsIG5vbmUgb2YgdGhlbSBhcmUgc3RyaWtpbmdseSBzbyB3aXRoIG1heGltdW0gLWxvZyhhZGp1c3RlZCBwLXZhbHVlcykgb25seSByZWFjaGluZyB1cCB0byBhYm91dCAzIG1heGltdW0sIHdoZXJlYXMgcGxvdHMgc2VlbiB3aXRoIHN0cm9uZ2VyIGZ1bmN0aW9uYWwgZW5yaWNobWVudCBwcmVzZW5jZSByZWFjaCB1cCBtdWNoIGhpZ2hlciB0b3dhcmRzIDEwLTE2Ky4KCiMgSW50ZXJwcmV0YXRpb24KCiMjIERvIHRoZSBvdmVyLXJlcHJlc2VudGF0aW9uIHJlc3VsdHMgc3VwcG9ydCBjb25jbHVzaW9ucyBvciBtZWNoYW5pc21zIGRpc2N1c3NlZCBpbiB0aGUgb3JpZ2luYWwgcGFwZXI/CgpUaGUgb3JpZ2luYWwgcGFwZXIgaW5jbHVkZXMgc3Vic3RhbnRpYWxseSBtb3JlIHByb2Nlc3Npbmcgb2YgdGhpcyBkYXRhIGluIGFkZGl0aW9uIHRvIHRoZSBzaW5nbGUtY2VsbCBSTkEgc2VxdWVuY2luZyBkYXRhIHRoZXkgYWNxdWlyZWQgaW4gdGFuZGVtLCBzbyBpdCBpcyBkaWZmaWN1bHQgdG8gc2F5IHdoZXRoZXIgdGhpcyBzdXBwb3J0cyB0aG9zZSByZXN1bHRzLiBOb25lIG9mIG15IHNpZ25pZmljYW50IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhcHBlYXIgdGhyb3VnaG91dCB0aGUgcmVwb3J0IHdoYXRzb2V2ZXIuIFRoZSBkaXNjdXNzaW9uIGFuZCByZXN1bHRzIHNlY3Rpb24gZm9yIHRoZSBidWxrIFJOQS1zZXF1ZW5jaW5nIGlzIHZlcnkgbGFja2x1c3RlciBjb21wYXJlZCB0byB0aGUgcmVzdCBvZiB0aGUgYW5hbHlzaXMgYW5kIHJlc3VsdHMgZm91bmQgYnkgc3BhdGlhbCByZXNvbHV0aW9uIG9mIHNpbmdsZS1jZWxsIFJOQSBzZXF1ZW5jaW5nLiBUaGUgUk5BIHNlcXVlbmNpbmcgaGVhdG1hcCBhcHBlYXJzIHNpbWlsYXIgdG8gbWluZSwgYWx0aG91Z2ggdGhleSB1c2VkIHNjYWxlZCBtZWFuIGludGVyYWN0aW9uIHNjb3JlIGFuZCBzdWJ0eXBlZCBvbmx5IGZvciBgRVJgIGFuZCBgVE5CQ2AgYXMgb3Bwb3NlZCB0byB0aGUgZm91ciBhdmFpbGFibGUgY2xpbmljYWwgc3VidHlwZXMuIEkgY2FuIHVuZGVyc3RhbmQgdGhpcyBhcHByb2FjaCBzaW5jZSB0aGUgYEhFUjJgIHN1YnR5cGUgcHJlc2VuY2Ugd2FzIHJlbGF0aXZlbHkgc21hbGwgY29tcGFyZWQgdG8gdGhlIHJlc3Qgb2YgdGhlIHNhbXBsZXMuCgpUaGVyZSBpcyBub3QgbXVjaCBmdW5jdGlvbmFsIGVucmljaG1lbnQgYXBwYXJlbnRseSBkaXN0aW5ndWlzaGluZyB0aGUgY2xhc3NpZmllZCBjbGluaWNhbCBzdWJ0eXBlcyBvZiBicmVhc3QgY2FuY2VyIGluIHRoaXMgZGF0YXNldDsgYWx0aG91Z2ggaWYgd2UgaGFkIHRvIGxvb2sgYXQgdGhlIG1vc3Qgc2lnbmlmaWNhbnQgdGVybShzKSwgb3VyIGFuYWx5c2lzIHdvdWxkIGRyYXcgb3VyIGF0dGVudGlvbiB0byBjYWRoZXJpbiBiaW5kaW5nLCBpZS4gW0dPOjAwNDUyOTZdKGh0dHBzOi8vYW1pZ28uZ2VuZW9udG9sb2d5Lm9yZy9hbWlnby90ZXJtL0dPOjAwNDUyOTYpLCBvZiB3aGljaCBpcyBub3QgcHJlc2VudCBpbiB0aGUgcGFwZXIncyBjb25jbHVzaW9ucy4gQXMgc3VjaCwgbXkgZmluZGluZ3MgZG8gbm90IHN1cHBvcnQgdGhlIG1lY2hhbmlzbXMgb3IgY29uY2x1c2lvbnMgZGlzY3Vzc2VkIGluIHRoZSBvcmlnaW5hbCBwYXBlciwgYWx0aG91Z2ggdGhhdCBkb2VzIG5vdCBkZW55IG15IGZpbmRpbmdzLgoKIyMgQ2FuIHlvdSBmaW5kIGV2aWRlbmNlLCBpZS4gcHVibGljYXRpb25zLCB0byBzdXBwb3J0IHNvbWUgb2YgdGhlIHJlc3VsdHMgdGhhdCB5b3Ugc2VlPyBIb3cgZG9lcyB0aGlzIGV2aWRlbmNlIHN1cHBvcnQgeW91ciByZXN1bHRzPwoKQ29udGludWluZyB3aXRoIHRoZSBtb3N0IHNpZ25pZmljYW50IEdPIHRlcm0gZnJvbSBvdXIgYW5hbHlzaXMtLWNhZGhlcmluIGJpbmRpbmctLXRoZXJlIGlzIHN1YnN0YW50aWFsIGV2aWRlbmNlIHRoYXQgY2FkaGVyaW5zIGFyZSBpbnRlZ3JhbCB0byBtYW1tYXJ5IGdsYW5kIGZ1bmN0aW9uLCBhbmQgbWlzZXhwcmVzc2lvbiBvZiBzdWNoIGxlYWRzIHRvIGluY3JlYXNlZCBtb3RpbGl0eSBhbmQgY29uc2VxdWVudGx5IGdyZWF0ZXIgbGlrZWxpaG9vZCBvZiBtZXRhc3Rhc2VzIGZvcm1hdGlvbiBbQGRlcnlja2UyMDA0bl0uIEUtY2FkaGVyaW4gaXMgb25lIG9mIHRoZSBtb3N0IHdpZGVseSBleHByZXNzZWQgdHVtb3VyIHN1cHByZXNzb3JzIGluIGJyZWFzdCBjYW5jZXIsIGhvd2V2ZXIgY2FkaGVyaW4tYmluZGluZyBvbiBpdHMgb3duIGlzIHJhdGhlciB2YWd1ZSBhbmQgZGlmZmljdWx0IHRvIGRyYXcgY29uY2x1c2lvbnMgZnJvbS4gV2UgY2FuIGNvbmNsdWRlLCBob3dldmVyLCB0aGF0IGNhZGhlcmlucyBhcmUgYXNzb2NpYXRlZCB3aXRoIGJyZWFzdCBjYW5jZXIgaW4gbXVsdGlwbGUgd2F5cywgYW5kIHNvIGNhZGhlcmluLWJpbmRpbmcgbWF5IGJlIGEgZGlzdGluZ3Vpc2hhYmxlIGZ1bmN0aW9uYWwgZW5yaWNobWVudCBiZXR3ZWVuIGNsaW5pY2FsIHN1YnR5cGVzLS1idXQgdGhpcyBjbGFpbSBpcyB0b28gZ2VuZXJhbCB0byBjb25maWRlbnRseSBiYWNrLgoKSW50ZXJlc3RpbmdseSwgb25lIG9mIG91ciB0aHJlZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhZnRlciBjb3JyZWN0aW9uIGFjcm9zcyBjbGluaWNhbCBzdWJ0eXBlcyBvZiBicmVhc3QgY2FuY2VyIGlzIGBBTlhBOGAgd2hpY2ggaXMgYXNzb2NpYXRlZCB3aXRoIGJyZWFzdCBjYW5jZXIgW0BtYWxhXS4gUm9zZXR0aSBldCBhbC4gc3VnZ2VzdGVkIGBBTlhBOGAgaXMgc2lnbmlmaWNhbnRseSBoaWdoZXIgaW4gYEVSLWAgc3VidHlwZXMgYXMgb3Bwb3NlZCB0byBgRVIrYCBzdWJ0eXBlcyBbQHJvc3NldHRpMjAxNmhhcm5lc3NpbmddIGJ1dCBpbnN0ZWFkIG9mIGZpbmRpbmcgdGhhdCBpbiBvdXIgcmVzdWx0cywgd2Ugbm90aWNlZCBgQU5YQThgIHdhcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBhY3Jvc3MgYWxsIGNsaW5pY2FsIHN1YnR5cGVzIGNsYXNzaWZpZWQgaW4gb3VyIHN0dWR5IGFuZCBub3Qgc3BlY2lmaWNhbGx5IGBFUmAgb3ZlcmV4cHJlc3Npb24gb3IgbGFjayB0aGVyZW9mLiBUaGlzIHdhcnJhbnRzIGludmVzdGlnYXRpb24gaW50byB3aHkgYEFOWEE4YCBpcyBleHByZXNzZWQgZGlmZmVyZW50aWFsbHkgaW4gYEVSYCBzdWJ0eXBlcyBhY2NvcmRpbmcgdG8gcmVzZWFyY2gsIHlldCBzZWxlY3RpdmVseSBleHByZXNzZWQgZGlmZmVyZW50aWFsbHkgYWNyb3NzIGFsbCBmb3VyIG9mIG91ciBjbGFzc2lmaWVkIGNsaW5pY2FsIHN1YnR5cGVzIG9mIGJyZWFzdCBjYW5jZXIsIGFuZCBub3Qgc3BlY2lmaWNhbGx5IGZvciBgRVJgIGluLXNpbGljby4KCkluIHRlcm1zIG9mIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGluIHJlZ2FyZHMgdG8gYEVSLWAgYW5kIGBFUitgIHNwZWNpZmljYWxseSwgdGhlIG1vc3Qgc2lnbmlmaWNhbnQgZ2VuZSBpcyBgRVBIQTNgIHdoaWNoIGhhcyBiZWVuIHNob3duIHRvIGJlIGV4dGVuc2l2ZWx5IG1vcmUgdXAtcmVndWxhdGVkIGluIGBFUitgIGJyZWFzdCBjYW5jZXJzIFtAbGlhbmcyMDIxZXhwcmVzc2lvbl0sIHdoaWNoIGRpcmVjdGx5IHN1cHBvcnRzIG15IGZpbmRpbmdzLiBBbHRob3VnaCBteSBmaW5kaW5ncyB3ZXJlIG5vdCByZWZsZWN0aXZlIG9mIHRoZSBtZWNoYW5pc21zIGFuZCBkaXJlY3Rpb24gb2YgdGhlIHBhcGVyIEkgcmV0cmlldmVkIHRoZSBkYXRhIGZyb20sIHRoZXkgYXJlIHN1cHBvcnRlZCBieSBvdGhlciBldmlkZW5jZSBpbiBjZXJ0YWluIHdheXMuCgpJbiBjb25jbHVzaW9uLCB0aGVyZSBpcyBzb21lIGFzc29jaWF0ZWQgZXZpZGVuY2UgdGhhdCBzdWdnZXN0cyBteSByZXN1bHRzIGhhdmUgYSBmb3VuZGF0aW9uIGluIGZ1bmN0aW9uYWwgYmlvbG9neSwgaG93ZXZlciBub3RoaW5nIGhhcyBhIHNpZ25pZmljYW5jZSB0aGF0IHdvdWxkIGdpdmUgbWUgY29uZmlkZW5jZSB0byBiYWNrIG15IGNsYWltLiBGb3IgdGhpcywgSSB3b3VsZCB3YW50IGEgcC12YWx1ZSBzbWFsbGVyIHRoYW4gYDEwZS0zYC4KCiMgQWNrbm93bGVkZ21lbnRzCgpUaGlzIHBhcGVyIG1ha2VzIHVzZSBvZiBwYWNrYWdlcyBga25pdHJgIFtAa25pdHIyMDE1XSwgYEJpb2NNYW5hZ2VyYCBbQGJpb2NtYW5hZ2VyXSwgYEdFT3F1ZXJ5YCBbQFItR0VPcXVlcnldLCBga2FibGVFeHRyYWAgW0BrYWJsZWV4dHJhXSwgYGVkZ2VSYCBbQFItZWRnZVJdLCBgbGltbWFgIFtAbGltbWEyMDE1XSwgYENvbXBsZXhIZWF0bWFwYCBbQGNvbXBsZXhoZWF0bWFwXSwgYGNpcmNsaXplYCBbQGNpcmNsaXplXSwgYGdwcm9maWxlcjJgIFtAZ3Byb2ZpbGVyMl0sIGBHU0FgIFtAZ3NhXSwgJiBgZ2dwbG90MmAgW0BSLWdncGxvdDJdLgoKIyBCaWJsaW9ncmFwaHkK